[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.
Regards,
alceste
--
Alceste Scalas <alceste@REDACTED>
CRS4 - http://www.crs4.it/
More information about the erlang-questions
mailing list