111 lines
3.0 KiB
JavaScript
111 lines
3.0 KiB
JavaScript
// Timer event driver
|
|
var Patch = require("./patch.js");
|
|
var DemandMatcher = require('./demand-matcher.js').DemandMatcher;
|
|
var Struct = require('./struct.js');
|
|
|
|
var Dataspace_ = require("./dataspace.js");
|
|
var Dataspace = Dataspace_.Dataspace;
|
|
var __ = Dataspace_.__;
|
|
var _$ = Dataspace_._$;
|
|
|
|
var periodicTick = Struct.makeConstructor('periodicTick', ['intervalMS']); // message
|
|
var timeLaterThan = Struct.makeConstructor('timeLaterThan', ['deadlineMS']); // assertion
|
|
|
|
function spawnTimerDriver() {
|
|
Dataspace.spawn(
|
|
new DemandMatcher([Patch.observe(periodicTick(_$('intervalMS')))],
|
|
[Patch.advertise(periodicTick(_$('intervalMS')))],
|
|
function (c) {
|
|
Dataspace.spawn(new Tick(c.intervalMS));
|
|
}));
|
|
Dataspace.spawn(
|
|
new DemandMatcher([Patch.observe(timeLaterThan(_$('deadlineMS')))],
|
|
[Patch.advertise(timeLaterThan(_$('deadlineMS')))],
|
|
function (c) {
|
|
Dataspace.spawn(new Alarm(c.deadlineMS));
|
|
}));
|
|
}
|
|
|
|
function Tick(intervalMS) {
|
|
this.intervalMS = intervalMS;
|
|
this.handle = null;
|
|
}
|
|
|
|
Tick.prototype.boot = function () {
|
|
var self = this;
|
|
this.handle = setInterval(Dataspace.wrap(function () {
|
|
Dataspace.send(periodicTick(self.intervalMS));
|
|
}), this.intervalMS);
|
|
|
|
return Patch.sub(Patch.observe(periodicTick(this.intervalMS))) // monitor interest
|
|
.andThen(Patch.pub(periodicTick(this.intervalMS))) // signal we exist to DemandMatcher
|
|
;
|
|
};
|
|
|
|
Tick.prototype.trapexit = function () {
|
|
this.cancelTimer();
|
|
};
|
|
|
|
Tick.prototype.cancelTimer = function () {
|
|
if (this.handle !== null) {
|
|
clearInterval(this.handle);
|
|
this.handle = null;
|
|
}
|
|
};
|
|
|
|
Tick.prototype.handleEvent = function (e) {
|
|
if (e.type === 'stateChange' && e.patch.hasRemoved()) {
|
|
Dataspace.exit();
|
|
}
|
|
};
|
|
|
|
function Alarm(deadlineMS) {
|
|
this.deadlineMS = deadlineMS;
|
|
this.handle = null;
|
|
}
|
|
|
|
Alarm.prototype.boot = function () {
|
|
this.checkTimeout();
|
|
|
|
return Patch.sub(Patch.observe(timeLaterThan(this.deadlineMS))) // monitor interest
|
|
.andThen(Patch.pub(timeLaterThan(this.deadlineMS))) // signal we exist to DemandMatcher
|
|
;
|
|
};
|
|
|
|
Alarm.prototype.checkTimeout = function () {
|
|
var now = +(new Date());
|
|
var delta = this.deadlineMS - now;
|
|
if (delta <= 0) {
|
|
Dataspace.stateChange(Patch.assert(timeLaterThan(this.deadlineMS)));
|
|
this.cancelTimer();
|
|
} else if (this.handle === null) {
|
|
var self = this;
|
|
this.handle = setTimeout(Dataspace.wrap(function () { self.checkTimeout(); }), delta);
|
|
}
|
|
};
|
|
|
|
Alarm.prototype.cancelTimer = function () {
|
|
if (this.handle !== null) {
|
|
clearTimeout(this.handle);
|
|
this.handle = null;
|
|
}
|
|
};
|
|
|
|
Alarm.prototype.trapexit = function () {
|
|
this.cancelTimer();
|
|
};
|
|
|
|
Alarm.prototype.handleEvent = function (e) {
|
|
if (e.type === 'stateChange' && e.patch.hasRemoved()) {
|
|
Dataspace.exit();
|
|
}
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
module.exports.spawnTimerDriver = spawnTimerDriver;
|
|
module.exports.periodicTick = periodicTick;
|
|
module.exports.timeLaterThan = timeLaterThan;
|
|
module.exports.Tick = Tick;
|
|
module.exports.Alarm = Alarm;
|