|  | module.exports = Pend; | 
|  |  | 
|  | function Pend() { | 
|  | this.pending = 0; | 
|  | this.max = Infinity; | 
|  | this.listeners = []; | 
|  | this.waiting = []; | 
|  | this.error = null; | 
|  | } | 
|  |  | 
|  | Pend.prototype.go = function(fn) { | 
|  | if (this.pending < this.max) { | 
|  | pendGo(this, fn); | 
|  | } else { | 
|  | this.waiting.push(fn); | 
|  | } | 
|  | }; | 
|  |  | 
|  | Pend.prototype.wait = function(cb) { | 
|  | if (this.pending === 0) { | 
|  | cb(this.error); | 
|  | } else { | 
|  | this.listeners.push(cb); | 
|  | } | 
|  | }; | 
|  |  | 
|  | Pend.prototype.hold = function() { | 
|  | return pendHold(this); | 
|  | }; | 
|  |  | 
|  | function pendHold(self) { | 
|  | self.pending += 1; | 
|  | var called = false; | 
|  | return onCb; | 
|  | function onCb(err) { | 
|  | if (called) throw new Error("callback called twice"); | 
|  | called = true; | 
|  | self.error = self.error || err; | 
|  | self.pending -= 1; | 
|  | if (self.waiting.length > 0 && self.pending < self.max) { | 
|  | pendGo(self, self.waiting.shift()); | 
|  | } else if (self.pending === 0) { | 
|  | var listeners = self.listeners; | 
|  | self.listeners = []; | 
|  | listeners.forEach(cbListener); | 
|  | } | 
|  | } | 
|  | function cbListener(listener) { | 
|  | listener(self.error); | 
|  | } | 
|  | } | 
|  |  | 
|  | function pendGo(self, fn) { | 
|  | fn(pendHold(self)); | 
|  | } |