UNPKG

1.9 kBJavaScriptView Raw
1/** @license MIT License (c) copyright 2011-2013 original author or authors */
2
3/**
4 * Generalized promise concurrency guard
5 * Adapted from original concept by Sakari Jokinen (Rocket Pack, Ltd.)
6 *
7 * @author Brian Cavalier
8 * @author John Hann
9 * @contributor Sakari Jokinen
10 */
11(function(define) {
12define(function(require) {
13
14 var when = require('./when');
15 var slice = Array.prototype.slice;
16
17 guard.n = n;
18
19 return guard;
20
21 /**
22 * Creates a guarded version of f that can only be entered when the supplied
23 * condition allows.
24 * @param {function} condition represents a critical section that may only
25 * be entered when allowed by the condition
26 * @param {function} f function to guard
27 * @returns {function} guarded version of f
28 */
29 function guard(condition, f) {
30 return function() {
31 var args = slice.call(arguments);
32
33 return when(condition()).withThis(this).then(function(exit) {
34 return when(f.apply(this, args))['finally'](exit);
35 });
36 };
37 }
38
39 /**
40 * Creates a condition that allows only n simultaneous executions
41 * of a guarded function
42 * @param {number} allowed number of allowed simultaneous executions
43 * @returns {function} condition function which returns a promise that
44 * fulfills when the critical section may be entered. The fulfillment
45 * value is a function ("notifyExit") that must be called when the critical
46 * section has been exited.
47 */
48 function n(allowed) {
49 var count = 0;
50 var waiting = [];
51
52 return function enter() {
53 return when.promise(function(resolve) {
54 if(count < allowed) {
55 resolve(exit);
56 } else {
57 waiting.push(resolve);
58 }
59 count += 1;
60 });
61 };
62
63 function exit() {
64 count = Math.max(count - 1, 0);
65 if(waiting.length > 0) {
66 waiting.shift()(exit);
67 }
68 }
69 }
70
71});
72}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));