Remember that although JavaScript is single-threaded, all node I / O and calls to its own APIs are either asynchronous (using platform-specific mechanisms) or performed in a separate thread. (All of this is handled through libuv.)
Therefore, when the return data is available in a socket or in-built API function, we need a synchronized way to call a JavaScript function that is interested in the specific event that just happened.
It is unsafe to simply call the JS function from the thread in which the native event occurred for the same reasons that you encountered in a regular multi-threaded application - race conditions, non-atomic memory access, etc.
So what we do is put the event in the queue in a thread-safe manner. In a simplified psuedocode, something like:
lock (queue) { queue.push(event); }
Then, back to the main JavaScript thread (but on the C side of things), we do something like:
while (true) { // this is the beginning of a tick lock (queue) { var tickEvents = copy(queue); // copy the current queue items into thread-local memory queue.empty(); // ..and empty out the shared queue } for (var i = 0; i < tickEvents.length; i++) { InvokeJSFunction(tickEvents[i]); } // this the end of the tick }
while (true) (which does not actually exist in the source code of the node, this is just illustrative) represents an event loop. The internal for calls the JS function for each event that was in the queue.
This is a checkmark: a synchronous call of zero or more callback functions associated with any external events. As soon as the queue is empty and the last function returns, the checkmark is completed. We go back to the beginning (next tick) and check for events that were added to the queue from other threads while our JavaScript was running.
What can add things to the queue?
process.nextTicksetTimeout / <T26>- I / O (material from
fs , net , etc.) crypto Processor functions like crypto streams, pbkdf2 and PRNG (which are actually an example ...)- any built-in modules that use the libuv work queue to make the synchronous calls to the C / C ++ library look asynchronous
josh3736 Nov 06 '13 at 21:52 2013-11-06 21:52
source share