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
							 |