/** @license MIT License (c) copyright 2011-2013 original author or authors */ /** * Generalized promise concurrency guard * Adapted from original concept by Sakari Jokinen (Rocket Pack, Ltd.) * * @author Brian Cavalier * @author John Hann * @contributor Sakari Jokinen */ (function(define) { define(function(require) { var when = require('./when'); var slice = Array.prototype.slice; guard.n = n; return guard; /** * Creates a guarded version of f that can only be entered when the supplied * condition allows. * @param {function} condition represents a critical section that may only * be entered when allowed by the condition * @param {function} f function to guard * @returns {function} guarded version of f */ function guard(condition, f) { return function() { var args = slice.call(arguments); return when(condition()).withThis(this).then(function(exit) { return when(f.apply(this, args))['finally'](exit); }); }; } /** * Creates a condition that allows only n simultaneous executions * of a guarded function * @param {number} allowed number of allowed simultaneous executions * @returns {function} condition function which returns a promise that * fulfills when the critical section may be entered. The fulfillment * value is a function ("notifyExit") that must be called when the critical * section has been exited. */ function n(allowed) { var count = 0; var waiting = []; return function enter() { return when.promise(function(resolve) { if(count < allowed) { resolve(exit); } else { waiting.push(resolve); } count += 1; }); }; function exit() { count = Math.max(count - 1, 0); if(waiting.length > 0) { waiting.shift()(exit); } } } }); }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));