You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					200 lines
				
				4.5 KiB
			
		
		
			
		
	
	
					200 lines
				
				4.5 KiB
			| 
											3 years ago
										 | 'use strict' | ||
|  | 
 | ||
|  | var xtend = require('xtend') | ||
|  | var reusify = require('reusify') | ||
|  | var defaults = { | ||
|  |   released: nop, | ||
|  |   results: true | ||
|  | } | ||
|  | 
 | ||
|  | function fastparallel (options) { | ||
|  |   options = xtend(defaults, options) | ||
|  | 
 | ||
|  |   var released = options.released | ||
|  |   var queue = reusify(options.results ? ResultsHolder : NoResultsHolder) | ||
|  |   var queueSingleCaller = reusify(SingleCaller) | ||
|  |   var goArray = options.results ? goResultsArray : goNoResultsArray | ||
|  |   var goFunc = options.results ? goResultsFunc : goNoResultsFunc | ||
|  | 
 | ||
|  |   return parallel | ||
|  | 
 | ||
|  |   function parallel (that, toCall, arg, done) { | ||
|  |     var holder = queue.get() | ||
|  |     done = done || nop | ||
|  |     if (toCall.length === 0) { | ||
|  |       done.call(that) | ||
|  |       released(holder) | ||
|  |     } else { | ||
|  |       holder._callback = done | ||
|  |       holder._callThat = that | ||
|  |       holder._release = release | ||
|  | 
 | ||
|  |       if (typeof toCall === 'function') { | ||
|  |         goFunc(that, toCall, arg, holder) | ||
|  |       } else { | ||
|  |         goArray(that, toCall, arg, holder) | ||
|  |       } | ||
|  | 
 | ||
|  |       if (holder._count === 0) { | ||
|  |         holder.release() | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   function release (holder) { | ||
|  |     queue.release(holder) | ||
|  |     released(holder) | ||
|  |   } | ||
|  | 
 | ||
|  |   function singleCallerRelease (holder) { | ||
|  |     queueSingleCaller.release(holder) | ||
|  |   } | ||
|  | 
 | ||
|  |   function goResultsFunc (that, toCall, arg, holder) { | ||
|  |     var singleCaller = null | ||
|  |     holder._count = arg.length | ||
|  |     holder._results = new Array(holder._count) | ||
|  |     for (var i = 0; i < arg.length; i++) { | ||
|  |       singleCaller = queueSingleCaller.get() | ||
|  |       singleCaller._release = singleCallerRelease | ||
|  |       singleCaller.parent = holder | ||
|  |       singleCaller.pos = i | ||
|  |       if (that) { | ||
|  |         toCall.call(that, arg[i], singleCaller.release) | ||
|  |       } else { | ||
|  |         toCall(arg[i], singleCaller.release) | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   function goResultsArray (that, funcs, arg, holder) { | ||
|  |     var sc = null | ||
|  |     var tc = nop | ||
|  |     holder._count = funcs.length | ||
|  |     holder._results = new Array(holder._count) | ||
|  |     for (var i = 0; i < funcs.length; i++) { | ||
|  |       sc = queueSingleCaller.get() | ||
|  |       sc._release = singleCallerRelease | ||
|  |       sc.parent = holder | ||
|  |       sc.pos = i | ||
|  |       tc = funcs[i] | ||
|  |       if (that) { | ||
|  |         if (tc.length === 1) tc.call(that, sc.release) | ||
|  |         else tc.call(that, arg, sc.release) | ||
|  |       } else { | ||
|  |         if (tc.length === 1) tc(sc.release) | ||
|  |         else tc(arg, sc.release) | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   function goNoResultsFunc (that, toCall, arg, holder) { | ||
|  |     holder._count = arg.length | ||
|  |     for (var i = 0; i < arg.length; i++) { | ||
|  |       if (that) { | ||
|  |         toCall.call(that, arg[i], holder.release) | ||
|  |       } else { | ||
|  |         toCall(arg[i], holder.release) | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   function goNoResultsArray (that, funcs, arg, holder) { | ||
|  |     var toCall = null | ||
|  |     holder._count = funcs.length | ||
|  |     for (var i = 0; i < funcs.length; i++) { | ||
|  |       toCall = funcs[i] | ||
|  |       if (that) { | ||
|  |         if (toCall.length === 1) { | ||
|  |           toCall.call(that, holder.release) | ||
|  |         } else { | ||
|  |           toCall.call(that, arg, holder.release) | ||
|  |         } | ||
|  |       } else { | ||
|  |         if (toCall.length === 1) { | ||
|  |           toCall(holder.release) | ||
|  |         } else { | ||
|  |           toCall(arg, holder.release) | ||
|  |         } | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | function NoResultsHolder () { | ||
|  |   this._count = -1 | ||
|  |   this._callback = nop | ||
|  |   this._callThat = null | ||
|  |   this._release = null | ||
|  |   this.next = null | ||
|  | 
 | ||
|  |   var that = this | ||
|  |   var i = 0 | ||
|  |   this.release = function () { | ||
|  |     var cb = that._callback | ||
|  |     if (++i === that._count || that._count === 0) { | ||
|  |       if (that._callThat) { | ||
|  |         cb.call(that._callThat) | ||
|  |       } else { | ||
|  |         cb() | ||
|  |       } | ||
|  |       that._callback = nop | ||
|  |       that._callThat = null | ||
|  |       i = 0 | ||
|  |       that._release(that) | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | function SingleCaller () { | ||
|  |   this.pos = -1 | ||
|  |   this._release = nop | ||
|  |   this.parent = null | ||
|  |   this.next = null | ||
|  | 
 | ||
|  |   var that = this | ||
|  |   this.release = function (err, result) { | ||
|  |     that.parent.release(err, that.pos, result) | ||
|  |     that.pos = -1 | ||
|  |     that.parent = null | ||
|  |     that._release(that) | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | function ResultsHolder () { | ||
|  |   this._count = -1 | ||
|  |   this._callback = nop | ||
|  |   this._results = null | ||
|  |   this._err = null | ||
|  |   this._callThat = null | ||
|  |   this._release = nop | ||
|  |   this.next = null | ||
|  | 
 | ||
|  |   var that = this | ||
|  |   var i = 0 | ||
|  |   this.release = function (err, pos, result) { | ||
|  |     that._err = that._err || err | ||
|  |     if (pos >= 0) { | ||
|  |       that._results[pos] = result | ||
|  |     } | ||
|  |     var cb = that._callback | ||
|  |     if (++i === that._count || that._count === 0) { | ||
|  |       if (that._callThat) { | ||
|  |         cb.call(that._callThat, that._err, that._results) | ||
|  |       } else { | ||
|  |         cb(that._err, that._results) | ||
|  |       } | ||
|  |       that._callback = nop | ||
|  |       that._results = null | ||
|  |       that._err = null | ||
|  |       that._callThat = null | ||
|  |       i = 0 | ||
|  |       that._release(that) | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | function nop () { } | ||
|  | 
 | ||
|  | module.exports = fastparallel |