I’ve been modifying an existing nodejs extension, that wraps libcwiid (a C library written to interface with a Wiimote). This extension uses polling to check if the state of the Wiimote has changed (such as a button being pressed). Libcwiid however provides a callback mechanism to be alerted as soon as a state change occurs. This has the benefit of being instantaneous, instead of at the polling interval.
While adapting nodewii to use this callback mechanism I learnt a couple of things about developing multi-threaded nodejs extensions that I thought I’d share.
1) All V8 operations must run from the main thread
eio_custom(eio_cb execute, int pri, eio_cb cb, void *data);
This simple pattern makes writing callback code relatively simple. However, this only works well if you are in control of creating the callback.
2) How to run something on the main thread without eio_custom
Libcwiid creates it’s own thread, which is uses to read data from the wiimote. When data is received, it invokes a callback function passing this new data. This callback function is run on the libcwiid thread. This restricts us from interacting with V8. We ideally need this callback function running in the context of the main thread. The answer to this problem is:
eio_req *eio_nop (int pri, eio_cb cb, void *data);
It is safe to call this function from any thread. It will place the eio_cb callback task on the main event queue. This task is then eventually executed on the V8′s thread. An example of this follows:
Using a combination of eio_custom and eio_nop you should be able to interface with any external library of service. You just have to make sure you always know what thread you are on, and what methods you are allowed to use in that context.
Finally, writing correct thread-safe code is hard. From the various nodejs extensions I have come across I regularlly find memory management, or threading issues with them. So I suggest you rigorously use valgrind while developing, and simplify your designs so that most of the heavily lifting is done by nodejs itself.