| 'use strict'; | 
|   | 
| Object.defineProperty(exports, "__esModule", { | 
|     value: true | 
| }); | 
| exports.default = queue; | 
|   | 
| var _baseIndexOf = require('lodash/_baseIndexOf'); | 
|   | 
| var _baseIndexOf2 = _interopRequireDefault(_baseIndexOf); | 
|   | 
| var _isArray = require('lodash/isArray'); | 
|   | 
| var _isArray2 = _interopRequireDefault(_isArray); | 
|   | 
| var _noop = require('lodash/noop'); | 
|   | 
| var _noop2 = _interopRequireDefault(_noop); | 
|   | 
| var _onlyOnce = require('./onlyOnce'); | 
|   | 
| var _onlyOnce2 = _interopRequireDefault(_onlyOnce); | 
|   | 
| var _setImmediate = require('./setImmediate'); | 
|   | 
| var _setImmediate2 = _interopRequireDefault(_setImmediate); | 
|   | 
| var _DoublyLinkedList = require('./DoublyLinkedList'); | 
|   | 
| var _DoublyLinkedList2 = _interopRequireDefault(_DoublyLinkedList); | 
|   | 
| var _wrapAsync = require('./wrapAsync'); | 
|   | 
| var _wrapAsync2 = _interopRequireDefault(_wrapAsync); | 
|   | 
| function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | 
|   | 
| function queue(worker, concurrency, payload) { | 
|     if (concurrency == null) { | 
|         concurrency = 1; | 
|     } else if (concurrency === 0) { | 
|         throw new Error('Concurrency must not be zero'); | 
|     } | 
|   | 
|     var _worker = (0, _wrapAsync2.default)(worker); | 
|     var numRunning = 0; | 
|     var workersList = []; | 
|   | 
|     var processingScheduled = false; | 
|     function _insert(data, insertAtFront, callback) { | 
|         if (callback != null && typeof callback !== 'function') { | 
|             throw new Error('task callback must be a function'); | 
|         } | 
|         q.started = true; | 
|         if (!(0, _isArray2.default)(data)) { | 
|             data = [data]; | 
|         } | 
|         if (data.length === 0 && q.idle()) { | 
|             // call drain immediately if there are no tasks | 
|             return (0, _setImmediate2.default)(function () { | 
|                 q.drain(); | 
|             }); | 
|         } | 
|   | 
|         for (var i = 0, l = data.length; i < l; i++) { | 
|             var item = { | 
|                 data: data[i], | 
|                 callback: callback || _noop2.default | 
|             }; | 
|   | 
|             if (insertAtFront) { | 
|                 q._tasks.unshift(item); | 
|             } else { | 
|                 q._tasks.push(item); | 
|             } | 
|         } | 
|   | 
|         if (!processingScheduled) { | 
|             processingScheduled = true; | 
|             (0, _setImmediate2.default)(function () { | 
|                 processingScheduled = false; | 
|                 q.process(); | 
|             }); | 
|         } | 
|     } | 
|   | 
|     function _next(tasks) { | 
|         return function (err) { | 
|             numRunning -= 1; | 
|   | 
|             for (var i = 0, l = tasks.length; i < l; i++) { | 
|                 var task = tasks[i]; | 
|   | 
|                 var index = (0, _baseIndexOf2.default)(workersList, task, 0); | 
|                 if (index === 0) { | 
|                     workersList.shift(); | 
|                 } else if (index > 0) { | 
|                     workersList.splice(index, 1); | 
|                 } | 
|   | 
|                 task.callback.apply(task, arguments); | 
|   | 
|                 if (err != null) { | 
|                     q.error(err, task.data); | 
|                 } | 
|             } | 
|   | 
|             if (numRunning <= q.concurrency - q.buffer) { | 
|                 q.unsaturated(); | 
|             } | 
|   | 
|             if (q.idle()) { | 
|                 q.drain(); | 
|             } | 
|             q.process(); | 
|         }; | 
|     } | 
|   | 
|     var isProcessing = false; | 
|     var q = { | 
|         _tasks: new _DoublyLinkedList2.default(), | 
|         concurrency: concurrency, | 
|         payload: payload, | 
|         saturated: _noop2.default, | 
|         unsaturated: _noop2.default, | 
|         buffer: concurrency / 4, | 
|         empty: _noop2.default, | 
|         drain: _noop2.default, | 
|         error: _noop2.default, | 
|         started: false, | 
|         paused: false, | 
|         push: function (data, callback) { | 
|             _insert(data, false, callback); | 
|         }, | 
|         kill: function () { | 
|             q.drain = _noop2.default; | 
|             q._tasks.empty(); | 
|         }, | 
|         unshift: function (data, callback) { | 
|             _insert(data, true, callback); | 
|         }, | 
|         remove: function (testFn) { | 
|             q._tasks.remove(testFn); | 
|         }, | 
|         process: function () { | 
|             // Avoid trying to start too many processing operations. This can occur | 
|             // when callbacks resolve synchronously (#1267). | 
|             if (isProcessing) { | 
|                 return; | 
|             } | 
|             isProcessing = true; | 
|             while (!q.paused && numRunning < q.concurrency && q._tasks.length) { | 
|                 var tasks = [], | 
|                     data = []; | 
|                 var l = q._tasks.length; | 
|                 if (q.payload) l = Math.min(l, q.payload); | 
|                 for (var i = 0; i < l; i++) { | 
|                     var node = q._tasks.shift(); | 
|                     tasks.push(node); | 
|                     workersList.push(node); | 
|                     data.push(node.data); | 
|                 } | 
|   | 
|                 numRunning += 1; | 
|   | 
|                 if (q._tasks.length === 0) { | 
|                     q.empty(); | 
|                 } | 
|   | 
|                 if (numRunning === q.concurrency) { | 
|                     q.saturated(); | 
|                 } | 
|   | 
|                 var cb = (0, _onlyOnce2.default)(_next(tasks)); | 
|                 _worker(data, cb); | 
|             } | 
|             isProcessing = false; | 
|         }, | 
|         length: function () { | 
|             return q._tasks.length; | 
|         }, | 
|         running: function () { | 
|             return numRunning; | 
|         }, | 
|         workersList: function () { | 
|             return workersList; | 
|         }, | 
|         idle: function () { | 
|             return q._tasks.length + numRunning === 0; | 
|         }, | 
|         pause: function () { | 
|             q.paused = true; | 
|         }, | 
|         resume: function () { | 
|             if (q.paused === false) { | 
|                 return; | 
|             } | 
|             q.paused = false; | 
|             (0, _setImmediate2.default)(q.process); | 
|         } | 
|     }; | 
|     return q; | 
| } | 
| module.exports = exports['default']; |