A very simple mutex for asynchronous code, which does not spin nor busy-wait. Also exports an efficient Queue.
When no other asynchronous activity has also locked key
, executes critical(unlock)
:
- The
key
is anything suitable for a key to a javascript object. - The
critical
function can be anything, but it must executeunlock()
sometime before it finishes (even if there is an error). For example:
lock(pathname, function (unlock) {
fs.writeFile(pathname, data, function (error) { unlock(); callback(error); });
});
The keys
argument can be an array of keys. critical
is not executed until each element in keys
is unlocked. This is preferred over a nested series of lock
s, in which the critical
section of each would have locked the next key in turn. The nested form is subject to deadlocks that do not occur when using an array of keys
.
This is a clone of Stephen Morley's Queue. The original code and a nice performance illustration is at http://code.stephenmorley.org/javascript/queues/
A queue is a first-in-first-out (FIFO) data structure. Items are added to the end of the queue and removed from the front. It's just like using Array
with push()
and shift()
, but faster. (The built-in javascript shift
has horrible performance for large arrays.)
This version is different from Stephen's only as follows:
- jslintable and strict
- node module export
- releases references to queued objects in dequeue, so that they can be gc'd. This is important for ki1r0y.lock, because the items being queued are closures that are not used after they are dequeued, and we really don't want to keep those around.
var q = new Queue();
This is analogous to var anArray = new Array();
q.enqueue(newElement)
This is analogous to anArray.push(newElement)
var oldestItem = q.dequeue();
This is analogous to anArray.shift()
, but much faster for long queues.
var oldestItem = q.peek();
This is analogous to anArray[0]
.
q.getLength(); # like anArray.length
q.isEmpty(); # like !anArray.length
There is a (somewhat weak) test suite at test/test.js