UNPKG

fwk

Version:

Simple JS framework for node.js

123 lines (107 loc) 3.39 kB
// Copyright Teleportd // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. var util = require('util'); var events = require('events'); var base = require("./base.js"); /** * lock.js * * A lock implementation for javascript, useful in some precise case where * multiple asynchronous events or callbacks should be ordered. * Each lock is in fact a collection of locks based on the tags passed. */ /** * A Lock * * @extends events.EventEmitter * * @param spec {} */ var lock = function(spec, my) { my = my || {}; var _super = {}; my.wlock = {}; my.rlock = {}; var that = new events.EventEmitter(); that.setMaxListeners(0); // public var rlock; /* rlock: acquires a read lock */ var wlock; /* wlock: acquires a write lock */ /** * rlock(tag, function(unlock) {... unlock(); }); * acquires a read lock then executes section */ rlock = function(tag, section_) { if(!my.wlock[tag]) { if(!my.rlock[tag]) my.rlock[tag] = 0; my.rlock[tag]++; var unlock = function() { //util.debug('READ UNLOCK: ' + tag); process.nextTick( function() { my.rlock[tag]--; if(my.rlock[tag] < 0) { my.rlock[tag] = 0; util.debug('WARNING: lock.js rlock < 0 for ' + tag); } that.emit(tag); }); }; /** read critical section */ //util.debug('READ CRITICAL: ' + tag); section_(unlock); } else { that.once(tag, function() { rlock(tag, section_); }); } }; /** * wlock(tag, function(unlock) {... unlock(); }); * acquires a write lock then executes section */ wlock = function(tag, section_) { if(!my.rlock[tag] && !my.wlock[tag]) { my.wlock[tag] = 1; var unlock = function() { //util.debug('WRITE UNLOCK: ' + tag); process.nextTick( function() { my.wlock[tag]--; if(my.wlock[tag] !== 0) { my.wlock[tag] = 0; util.debug('WARNING: lock.js wlock !== 0 for ' + tag); } that.emit(tag); }); }; /** write critical section */ //util.debug('WRITE CRITICAL: ' + tag); section_(unlock); } else { that.once(tag, function() { wlock(tag, section_); }); } }; base.method(that, 'rlock', rlock); base.method(that, 'wlock', wlock); return that; }; exports.lock = lock;