Blame view

node_modules/when/guard.js 1.85 KB
ce4c83ff   wxy   初始提交
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  /** @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); }));