[erlang-questions] Erlang callbacks, linked-in drivers and threads

Alceste Scalas alceste@REDACTED
Wed Dec 12 16:24:17 CET 2007

Il giorno mer, 12/12/2007 alle 10.33 +0000, Joel Reymont ha scritto:
> On Dec 12, 2007, at 10:13 AM, Alceste Scalas wrote:
> >        An Erlang callback is evaluated in the same process that
> >        performs the FFI call that causes the callback invocation.
> This won't work in the context of a Cocoa bridge, for example. Your  
> callback could be called at any point in time and it would be strictly  
> a C to Erlang invocation.

I'm not familiar with Cocoa.  But if it works (almost) like GTK+, I
suppose that it uses its own execution loop, and you want it to run in
its own thread, in parallel with the Erlang VM.  Erlang callbacks, thus,
may be called anytime from that thread.

If this is the case, then it is out of the context of my FFI proposal,
since (as I wrote in my previous email) it does not support threading.
Also, I don't see how the Erlang VM could handle "unexpected" function
calls, i.e. performed outside the Erlang process scheduling.

Here are some ideas on how to handle this situation, using the linked-in
driver API (that does support threads and messages).  When the Cocoa
binding is given an Erlang callback, maybe something like the following
could happen:

     1. the callback fun() is given a key and is added to a dictionary
        of available Erlang callbacks; 
     2. Cocoa, instead, receives a callback stub that wraps a proxy
        callback function (written in C), based on the Erlang driver
        API. The stub is generated on-the-fly (using libffi closures)
        and its signature reflects the Erlang callback signature (i.e.
        the one expected by Cocoa, too).  It also carries the key of the
        associated Erlang callback. 
     3. when the stub is called, it invokes the proxy, that converts all
        the stub parameters into Erlang terms and sends them to the port
        owner process; it also sends the key that identifies the Erlang
        callback, a buffer address for storing the return value, and an
        ErlDrvCond reference.  Then it sleeps on the ErlDrvCond itself
        until the return value becomes available; 
     4. the port owner process uses the key and parameters to invoke the
        Erlang callback; 
     5. the Erlang callback return value, the buffer address and the
        ErlDrvCond reference are sent back to the driver port; 
     6. the driver stores the return value in the buffer, and signals
        the ErlDrvCond; 
     7. the callback proxy wakes up, converts the Erlang return value
        found inside the buffer into the proper C type, and returns it
        to the callback stub, and, in turn, to the caller (that was
        waiting since point 3).

It's not exactly straightforward and fast --- but once it has been
written down, the "Erlang callbacks from linked-in drivers" code could
be generic enough to be reusable by other library bindings as well.


Alceste Scalas <alceste@REDACTED>
CRS4 - http://www.crs4.it/

More information about the erlang-questions mailing list