| 1 | | /* vim: set expandtab tabstop=2 shiftwidth=2 foldmethod=marker: */ |
| 2 | | |
| 3 | 1 | "use strict"; |
| 4 | | |
| 5 | 1 | var util = require('util'); |
| 6 | 1 | var Emitter = require('events').EventEmitter; |
| 7 | | |
| 8 | 1 | exports.create = function (options) { |
| 9 | | |
| 10 | 2 | var _options = { |
| 11 | | 'timeout' : 0, |
| 12 | | 'maxitem' : -1, |
| 13 | | }; |
| 14 | 2 | for (var i in options) { |
| 15 | 4 | _options[i] = options[i]; |
| 16 | | } |
| 17 | | |
| 18 | | /** |
| 19 | | * @序列 |
| 20 | | */ |
| 21 | 2 | var _sequence = []; |
| 22 | | |
| 23 | | /* {{{ private function build() */ |
| 24 | | /** |
| 25 | | * To build a timeout item into _sequence |
| 26 | | */ |
| 27 | 2 | var build = function (item, tmout, _self) { |
| 28 | 10 | var tmout = ~~(tmout || _options.timeout); |
| 29 | 10 | var _item = [item, 0]; |
| 30 | 10 | if (tmout) { |
| 31 | 8 | _item[1] = setTimeout(function () { |
| 32 | 2 | var i = _sequence.indexOf(_item); |
| 33 | 2 | if (i > -1) { |
| 34 | 2 | _sequence.splice(i, 1); |
| 35 | 2 | _self.emit('timeout', item, tmout, i); |
| 36 | | } |
| 37 | | }, tmout); |
| 38 | | } |
| 39 | 10 | return _item; |
| 40 | | }; |
| 41 | | /* }}} */ |
| 42 | | |
| 43 | | /* {{{ private function parse() */ |
| 44 | | /** |
| 45 | | * To parse and return a build-in item |
| 46 | | * |
| 47 | | * @ access private |
| 48 | | * @ param {Array} item |
| 49 | | * @ return {Object} or undefined |
| 50 | | */ |
| 51 | 2 | var parse = function (item) { |
| 52 | 4 | if (item && Array.isArray(item)) { |
| 53 | 3 | clearTimeout(item[1]); |
| 54 | 3 | item = item[0]; |
| 55 | | } |
| 56 | | |
| 57 | 4 | return item; |
| 58 | | }; |
| 59 | | /* }}} */ |
| 60 | | |
| 61 | 2 | var Queue = function () { |
| 62 | 2 | Emitter.call(this); |
| 63 | | }; |
| 64 | 2 | util.inherits(Queue, Emitter); |
| 65 | | |
| 66 | | /* {{{ public prototype push() */ |
| 67 | | /** |
| 68 | | * Push an item into sequence |
| 69 | | * |
| 70 | | * @ access public |
| 71 | | * @ param {Object} item |
| 72 | | * @ param {Integer} tmout |
| 73 | | * @ return {Number} length of the sequence |
| 74 | | */ |
| 75 | 2 | Queue.prototype.push = function (item, tmout) { |
| 76 | 11 | if (_options.maxitem > 0 && _sequence.length >= _options.maxitem) { |
| 77 | 1 | this.emit('full', _sequence.length, _options.maxitem); |
| 78 | 1 | return -1; |
| 79 | | } |
| 80 | | |
| 81 | 10 | var n = _sequence.push(build(item, tmout, this)); |
| 82 | 10 | if (1 === n) { |
| 83 | 3 | this.emit('fill'); |
| 84 | | } |
| 85 | | |
| 86 | 10 | return n; |
| 87 | | }; |
| 88 | | /* }}} */ |
| 89 | | |
| 90 | | /* {{{ public prototype shift() */ |
| 91 | | /** |
| 92 | | * shift an item from the sequence |
| 93 | | * |
| 94 | | * @ access public |
| 95 | | * @ return {Object} item or undefined |
| 96 | | */ |
| 97 | 2 | Queue.prototype.shift = function () { |
| 98 | 3 | return parse(_sequence.shift()); |
| 99 | | }; |
| 100 | | /* }}} */ |
| 101 | | |
| 102 | | /* {{{ public prototype pop() */ |
| 103 | | /** |
| 104 | | * Pop up an item from the sequence |
| 105 | | */ |
| 106 | 2 | Queue.prototype.pop = function () { |
| 107 | 1 | return parse(_sequence.pop()); |
| 108 | | }; |
| 109 | | /* }}} */ |
| 110 | | |
| 111 | | /* {{{ public prototype size() */ |
| 112 | 2 | Queue.prototype.size = function () { |
| 113 | 7 | return _sequence.length; |
| 114 | | }; |
| 115 | | /* }}} */ |
| 116 | | |
| 117 | | /* {{{ public prototype clean() */ |
| 118 | | /** |
| 119 | | * Clean the sequence up |
| 120 | | */ |
| 121 | 2 | Queue.prototype.clean = function () { |
| 122 | 1 | _sequence.forEach(function (item) { |
| 123 | 5 | if (item[1]) { |
| 124 | 5 | clearTimeout(item[1]); |
| 125 | | } |
| 126 | | }); |
| 127 | 1 | _sequence = []; |
| 128 | | }; |
| 129 | | /* }}} */ |
| 130 | | |
| 131 | 2 | return new Queue(); |
| 132 | | }; |