[erlang-questions] driver asyncronous notifications
Serge Aleynikov
saleyn@REDACTED
Fri Jun 1 05:30:40 CEST 2007
Greetings!
I wanted to consult with the list on the following subject. In the past
couple of weeks I have been writing an Erlang driver for TibcoRV. This
messaging system has a proprietary API with a multi-threaded engine.
The engine consists of a producer/consumer pair of threads that dispatch
and enqueue messages and also allows to register an event callback
triggered on every dequeued message.
In order to interface with an Erlang driver, I need in the event
callback to convert an RV message to an Erlang term and send it to the
emulator's thread via driver_output family of functions. The main
problem is that the driver API is mostly suited for three sorts of tasks:
a. Detection of activity on some registered file descriptor that
triggers ready_{input,output} callbacks in the context of the emulator's
thread.
b. A short-lived non-blocking request initiated from an Erlang process
(in the driver-space called via output*() or call() callback functions)
and followed by driver_output call to return result to the Erlang side.
c. A long-lived asynchronous request via driver_async() call, executed
in the context of a thread from a managed thread-pool with the result
returned by the async_ready() callback.
None of these three cases are suited for events that don't come on file
descriptors, but on callbacks in the context of other threads.
Unfortunately those callbacks cannon make direct use of driver_output*
non thread-safe functions. One possibility is to create a pipe and
register a read-end of the pipe with Erlang's select loop by calling
driver_select() function, and use write() call on the other end of the
pine from another thread to communicate some activity, so that if would
trigger the ready_input() driver's callback in the context of emulator's
thread. However this is a very expensive solution which I wouldn't want
to use.
Also driver_async() call is not very efficient in this case either
because when called from ThreadC, it'll execute a given function (that
doesn't really need to do anything since ThreadC in the RV's callback
function already have done all the work of creating an Erlang term to be
sent to the emulator) in the context of a ThreadB from a thread-pool and
then return to the emulator's ThreadA that can finally call
driver_output(). As you see, there is an unnecessary use of ThreadB in
this case that leads to performance loss. For reference, I implemented
this approach and got performance of 25,000 msgs/sec at 100% CPU
utilization, which is not quite suitable for the application I am
building (my C implementation gives over 60,000 msgs/sec).
Perhaps I am missing something here. How can I send a message
originated from some 3rd party callback function in the context of
ThreadC (that is not a part of a thread pool managed by Erlang) to the
emulator's ThreadA so that it would become aware of the new event and
safely deliver this message to a mailbox of an Erlang process (i.e. call
driver_output)?
Serge
More information about the erlang-questions
mailing list