libtimer
Version:
Basic timer lib helpers
414 lines (380 loc) • 14.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Timer = exports.TimerHeap = exports.TimerTask = exports.getTime = undefined;
var _getPrototypeOf = require("babel-runtime/core-js/object/get-prototype-of");
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
var _possibleConstructorReturn2 = require("babel-runtime/helpers/possibleConstructorReturn");
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require("babel-runtime/helpers/inherits");
var _inherits3 = _interopRequireDefault(_inherits2);
var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck");
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require("babel-runtime/helpers/createClass");
var _createClass3 = _interopRequireDefault(_createClass2);
var _obs = require("libobs/lib/obs");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var getTime = exports.getTime = function getTime() {
return Date.now();
}; /** @babel */
var TimerTask = exports.TimerTask = function () {
function TimerTask() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
_ref$run = _ref.run,
run = _ref$run === undefined ? null : _ref$run;
(0, _classCallCheck3.default)(this, TimerTask);
this.when = 0;
this.period = 0;
this.fixedRate = false;
this.cancelled = false;
this.scheduledTime = 0;
if (run) {
this.run = run;
}
}
(0, _createClass3.default)(TimerTask, [{
key: "cancel",
value: function cancel() {
var willRun = !this.cancelled && this.when > 0;
this.cancelled = true;
return willRun;
}
}, {
key: "getWhen",
value: function getWhen() {
return this.when;
}
}, {
key: "isScheduled",
value: function isScheduled() {
return this.when > 0 || this.scheduledTime > 0;
}
}, {
key: "run",
value: function run() {}
}, {
key: "scheduledExecutionTime",
value: function scheduledExecutionTime() {
return this.scheduledTime;
}
}, {
key: "setScheduledTime",
value: function setScheduledTime(time) {
this.scheduledTime = time;
}
}]);
return TimerTask;
}();
var DEFAULT_HEAP_SIZE = 256;
var TimerHeap = exports.TimerHeap = function (_Observable) {
(0, _inherits3.default)(TimerHeap, _Observable);
function TimerHeap() {
var heapSize = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_HEAP_SIZE;
(0, _classCallCheck3.default)(this, TimerHeap);
var _this = (0, _possibleConstructorReturn3.default)(this, (TimerHeap.__proto__ || (0, _getPrototypeOf2.default)(TimerHeap)).call(this));
_this.deletedCancelledNumber = _this.size = 0;
_this.heapSize = heapSize;
_this.timers = new Array(_this.heapSize);
return _this;
}
(0, _createClass3.default)(TimerHeap, [{
key: "adjustMinimum",
value: function adjustMinimum() {
this.downHeap(0);
}
}, {
key: "deleteIfCancelled",
value: function deleteIfCancelled() {
for (var i = 0; i < this.size; i++) {
var timer = this.timers[i];
if (timer.cancelled) {
this.deletedCancelledNumber++;
this.remove(i);
i--;
}
}
}
}, {
key: "downHeap",
value: function downHeap() {
var pos = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var current = pos;
var child = 2 * current + 1;
while (child < this.size && this.size > 0) {
if (child + 1 < this.size && this.timers[child + 1].when < this.timers[child].when) {
child++;
}
if (this.timers[current].when < this.timers[child].when) {
break;
}
var tmp = this.timers[current];
this.timers[current] = this.timers[child];
this.timers[child] = tmp;
current = child;
child = 2 * current + 1;
}
}
}, {
key: "getTask",
value: function getTask(task) {
for (var i = 0; i < this.timers.length; i++) {
var timer = this.timers[i];
if (timer === task) {
return i;
}
}
return -1;
}
}, {
key: "insert",
value: function insert(task) {
this.timers[this.size++] = task;
this.upHeap();
this.setChanged();
this.notifyObservers(this.size);
}
}, {
key: "isEmpty",
value: function isEmpty() {
return this.size === 0;
}
}, {
key: "minimum",
value: function minimum() {
return this.timers[0];
}
}, {
key: "remove",
value: function remove(pos) {
if (pos >= 0 && pos < this.size) {
this.timers[pos] = this.timers[--this.size];
this.timers[this.size] = null;
this.downHeap(pos);
this.setChanged();
this.notifyObservers(pos);
}
}
}, {
key: "reset",
value: function reset() {
this.timers = new Array(this.heapSize);
this.size = 0;
}
}, {
key: "upHeap",
value: function upHeap() {
var current = this.size - 1;
var parent = (current - 1) / 2;
if (current >= 0 && parent >= 0) {
while (this.timers[current].when < this.timers[parent].when) {
var tmp = this.timers[current];
this.timers[current] = this.timers[parent];
this.timers[parent] = tmp;
current = parent;
parent = (current - 1) / 2;
}
}
}
}]);
return TimerHeap;
}(_obs.Observable);
var Timer = exports.Timer = function (_Observer) {
(0, _inherits3.default)(Timer, _Observer);
function Timer() {
var heapSize = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_HEAP_SIZE;
(0, _classCallCheck3.default)(this, Timer);
var _this2 = (0, _possibleConstructorReturn3.default)(this, (Timer.__proto__ || (0, _getPrototypeOf2.default)(Timer)).call(this));
_this2.cancelled = _this2.finished = false;
_this2.tasks = new TimerHeap(heapSize);
_this2.tasks.addObserver(_this2);
return _this2;
}
(0, _createClass3.default)(Timer, [{
key: "cancel",
value: function cancel() {
this.cancelled = true;
this.tasks.reset();
}
}, {
key: "insertTask",
value: function insertTask(newTask) {
this.tasks.insert(newTask);
}
}, {
key: "purge",
value: function purge() {
if (this.tasks.isEmpty()) {
return 0;
}
this.tasks.deletedCancelledNumber = 0;
this.tasks.deleteIfCancelled();
return this.tasks.deletedCancelledNumber;
}
}, {
key: "run",
value: function run() {
if (this.cancelled) {
return;
}
if (this.tasks.isEmpty()) {
if (this.finished) {
return;
}
} else {
var currentTime = getTime();
var task = this.tasks.minimum();
if (task.cancelled) {
this.tasks.remove(0);
return;
}
var timeToSleep = task.when - currentTime;
if (timeToSleep > 0) {
this.wait(timeToSleep);
} else {
var pos = 0;
if (this.tasks.minimum().when !== task.when) {
pos = this.tasks.getTask(task);
}
if (task.cancelled) {
this.tasks.remove(this.tasks.getTask(task));
return;
}
task.setScheduledTime(task.when);
this.tasks.remove(pos);
if (task.period >= 0) {
if (task.fixedRate) {
task.when = task.when + task.period;
} else {
task.when = getTime() + task.period;
}
this.insertTask(task);
} else {
task.when = 0;
}
var taskCompletedNormally = false;
try {
task.run();
taskCompletedNormally = true;
} catch (e) {
console.error(e);
} finally {
if (!taskCompletedNormally) {
this.cancelled = true;
}
}
}
}
}
}, {
key: "schedule",
value: function schedule() {
var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
task = _ref2.task,
_ref2$when = _ref2.when,
when = _ref2$when === undefined ? null : _ref2$when,
_ref2$period = _ref2.period,
period = _ref2$period === undefined ? -1 : _ref2$period,
_ref2$delay = _ref2.delay,
delay = _ref2$delay === undefined ? -1 : _ref2$delay;
if (!task) {
throw new ReferenceError("NullPointerException task is null");
}
if (when && period) {
if (when.getTime() < 0 || period <= 0) {
throw new RangeError("IllegalArgumentException when < 0: " + when + " || period < 0 " + period);
}
var _delay = when.getTime() - getTime();
this.scheduleImpl({ task: task, delay: _delay < 0 ? 0 : _delay, period: period, fixed: false });
} else if (when) {
if (when.getTime() < 0) {
throw new RangeError("IllegalArgumentException when < 0: " + when.getTime());
}
var _delay2 = when.getTime() - getTime();
this.scheduleImpl({ task: task, delay: _delay2 < 0 ? 0 : _delay2, period: -1, fixed: false });
} else if (delay && period) {
if (delay < 0 || period <= 0) {
throw new RangeError("IllegalArgumentException delay < 0: " + delay + " || period < 0 " + period);
}
this.scheduleImpl({ task: task, delay: delay, period: period, fixed: false });
} else if (delay) {
if (delay < 0) {
throw new RangeError("IllegalArgumentException delay < 0: " + delay);
}
this.scheduleImpl({ task: task, delay: delay, period: -1, fixed: false });
}
}
}, {
key: "scheduleAtFixedRate",
value: function scheduleAtFixedRate() {
var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
task = _ref3.task,
_ref3$when = _ref3.when,
when = _ref3$when === undefined ? null : _ref3$when,
_ref3$period = _ref3.period,
period = _ref3$period === undefined ? -1 : _ref3$period,
_ref3$delay = _ref3.delay,
delay = _ref3$delay === undefined ? -1 : _ref3$delay;
if (!task) {
throw new ReferenceError("NullPointerException task is null");
}
if (when && period) {
if (when.getTime() < 0 || period <= 0) {
throw new RangeError("IllegalArgumentException when < 0: " + when + " || period < 0 " + period);
}
var _delay3 = when.getTime() - getTime();
this.scheduleImpl({ task: task, delay: _delay3 < 0 ? 0 : _delay3, period: period, fixed: true });
} else if (delay && period) {
if (delay < 0 || period <= 0) {
throw new RangeError("IllegalArgumentException delay < 0: " + delay + " || period < 0 " + period);
}
this.scheduleImpl({ task: task, delay: delay, period: period, fixed: true });
}
}
}, {
key: "scheduleImpl",
value: function scheduleImpl() {
var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
task = _ref4.task,
_ref4$period = _ref4.period,
period = _ref4$period === undefined ? -1 : _ref4$period,
_ref4$delay = _ref4.delay,
delay = _ref4$delay === undefined ? -1 : _ref4$delay,
_ref4$fixed = _ref4.fixed,
fixed = _ref4$fixed === undefined ? false : _ref4$fixed;
if (this.cancelled) {
throw new Error("IllegalStateException Timer was canceled");
}
var when = delay + getTime();
if (when < 0) {
throw new RangeError("IllegalArgumentException Illegal delay to start the TimerTask: " + when);
}
if (task.isScheduled()) {
throw new Error("IllegalStateException TimerTask is scheduled already");
}
if (task.cancelled) {
throw new Error("IllegalStateException TimerTask is canceled");
}
task.when = when;
task.period = period;
task.fixedRate = fixed;
this.insertTask(task);
}
}, {
key: "update",
value: function update(timerHeap, pos) {
this.run();
}
}, {
key: "wait",
value: function wait(time) {
var _this3 = this;
var tid = setTimeout(function () {
clearTimeout(tid);
tid = -1;
_this3.run();
}, time);
}
}]);
return Timer;
}(_obs.Observer);