[erlang-questions] driver asyncronous notifications

Serge Aleynikov <>
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