Module activation and main program start

This commit is contained in:
Tony Garnock-Jones 2018-11-01 23:30:17 +00:00
parent 2002d0975e
commit e4782b8406
4 changed files with 93 additions and 14 deletions

View File

@ -74,6 +74,6 @@ new Ground(() => {
return [Syndicate.Observe(BoxState(_$)), handler]; return [Syndicate.Observe(BoxState(_$)), handler];
}); });
}); });
}).start().stopHandler = () => { }).start().addStopHandler(() => {
console.timeEnd('box-and-client-' + N.toString()); console.timeEnd('box-and-client-' + N.toString());
}; });

View File

@ -38,20 +38,26 @@ const PRIORITY = Object.freeze({
_count: 6 _count: 6
}); });
function Dataspace(bootProc) { function Dataspace(container, bootProc) {
this.nextId = 0; this.nextId = 0;
this.container = container;
this.index = new Skeleton.Index(); this.index = new Skeleton.Index();
this.dataflow = new Dataflow.Graph(); this.dataflow = new Dataflow.Graph();
this.runnable = Immutable.List(); this.runnable = Immutable.List();
this.pendingActions = Immutable.List([ this.pendingActions = Immutable.List([
new ActionGroup(null, Immutable.List([new Spawn(null, bootProc, Immutable.Set())]))]); new ActionGroup(null, Immutable.List([new Spawn(null, bootProc, Immutable.Set())]))]);
this.activatedModules = Immutable.Set();
} }
// Parameters // Parameters
Dataspace._currentFacet = null; Dataspace._currentFacet = null;
Dataspace._inScript = true; Dataspace._inScript = true;
Dataspace.currentFacet = function () { return Dataspace._currentFacet; }; Dataspace.BootSteps = Symbol('SyndicateBootSteps');
Dataspace.currentFacet = function () {
return Dataspace._currentFacet;
};
Dataspace.withNonScriptContext = function (thunk) { Dataspace.withNonScriptContext = function (thunk) {
let savedInScript = Dataspace._inScript; let savedInScript = Dataspace._inScript;
@ -84,11 +90,36 @@ Dataspace.wrap = function (f) {
return function () { return function () {
let actuals = arguments; let actuals = arguments;
return Dataspace.withCurrentFacet(savedFacet, function () { return Dataspace.withCurrentFacet(savedFacet, function () {
return f.apply(f.fields, actuals); return f.apply(savedFacet.fields, actuals);
}); });
}; };
}; };
Dataspace.wrapExternal = function (f) {
let savedFacet = Dataspace._currentFacet;
let ac = savedFacet.actor;
return function () {
let actuals = arguments;
ac.dataspace.container.start();
ac.pushScript(function () {
Dataspace.withCurrentFacet(savedFacet, function () {
f.apply(this, actuals);
});
});
};
};
Dataspace.backgroundTask = function (k) {
let ground = Dataspace._currentFacet.actor.dataspace.container;
let active = true;
ground.backgroundTaskCount++;
return k(() => {
if (active) {
ground.backgroundTaskCount--;
active = false;
}
});
};
Dataspace.referenceField = function (obj, prop) { Dataspace.referenceField = function (obj, prop) {
if (!(prop in obj)) { if (!(prop in obj)) {
@ -162,7 +193,7 @@ Dataspace.prototype.addActor = function (name, bootProc, initialAssertions) {
ac.addFacet(null, () => { ac.addFacet(null, () => {
// Root facet is a dummy "system" facet that exists to hold // Root facet is a dummy "system" facet that exists to hold
// one-or-more "user" "root" facets. // one-or-more "user" "root" facets.
ac.addFacet(Dataspace.currentFacet(), bootProc); ac.addFacet(Dataspace._currentFacet, bootProc);
// ^ The "true root", user-visible facet. // ^ The "true root", user-visible facet.
initialAssertions.forEach((a) => { ac.adhocRetract(a); }); initialAssertions.forEach((a) => { ac.adhocRetract(a); });
}); });
@ -326,7 +357,7 @@ Message.prototype.perform = function (ds, ac) {
}; };
Dataspace.send = function (body) { Dataspace.send = function (body) {
Dataspace._currentFacet.actor.enqueueScriptAction(new Message(body)); Dataspace._currentFacet.enqueueScriptAction(new Message(body));
}; };
function Spawn(name, bootProc, initialAssertions) { function Spawn(name, bootProc, initialAssertions) {
@ -340,8 +371,7 @@ Spawn.prototype.perform = function (ds, ac) {
}; };
Dataspace.spawn = function (name, bootProc, initialAssertions) { Dataspace.spawn = function (name, bootProc, initialAssertions) {
let a = new Spawn(name, bootProc, initialAssertions); Dataspace._currentFacet.enqueueScriptAction(new Spawn(name, bootProc, initialAssertions));
Dataspace._currentFacet.actor.enqueueScriptAction(a);
}; };
function Quit() { // TODO: rename? Perhaps to Cleanup? function Quit() { // TODO: rename? Perhaps to Cleanup?
@ -361,7 +391,28 @@ DeferredTurn.prototype.perform = function (ds, ac) {
}; };
Dataspace.deferTurn = function (continuation) { Dataspace.deferTurn = function (continuation) {
Dataspace._currentFacet.actor.enqueueScriptAction(new DeferredTurn(Dataspace.wrap(continuation))); Dataspace._currentFacet.enqueueScriptAction(new DeferredTurn(Dataspace.wrap(continuation)));
};
function Activation(mod) {
this.mod = mod;
}
Activation.prototype.perform = function (ds, ac) {
if (!ds.activatedModules.includes(this.mod)) {
ds.activatedModules = ds.activatedModules.add(this.mod);
this.mod.exports[Dataspace.BootSteps].steps.forEach((a) => {
a.perform(ds, ac);
});
}
};
Dataspace.activate = function (modExports) {
let { module } = modExports[Dataspace.BootSteps] || {};
if (module) {
Dataspace._currentFacet.enqueueScriptAction(new Activation(module));
}
return modExports;
}; };
function ActionGroup(actor, actions) { function ActionGroup(actor, actions) {
@ -473,6 +524,10 @@ Facet.prototype.addDataflow = function (subjectFun, priority) {
}); });
}; };
Facet.prototype.enqueueScriptAction = function (action) {
this.actor.enqueueScriptAction(action);
};
Facet.prototype.toString = function () { Facet.prototype.toString = function () {
let s = 'Facet(' + this.actor.id; let s = 'Facet(' + this.actor.id;
if (this.actor.name !== void 0) s = s + ',' + JSON.stringify(this.actor.name); if (this.actor.name !== void 0) s = s + ',' + JSON.stringify(this.actor.name);
@ -485,6 +540,14 @@ Facet.prototype.toString = function () {
return s + ')'; return s + ')';
}; };
function ActionCollector() {
this.actions = [];
}
ActionCollector.prototype.enqueueScriptAction = function (a) {
this.actions.push(a);
};
function Endpoint(facet, isDynamic, updateFun) { function Endpoint(facet, isDynamic, updateFun) {
if (Dataspace._inScript) { if (Dataspace._inScript) {
throw new Error("Cannot add endpoint in script; are you missing a `react { ... }`?"); throw new Error("Cannot add endpoint in script; are you missing a `react { ... }`?");
@ -536,3 +599,4 @@ Endpoint.prototype.toString = function () {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
module.exports.Dataspace = Dataspace; module.exports.Dataspace = Dataspace;
module.exports.ActionCollector = ActionCollector;

View File

@ -7,8 +7,9 @@ function Ground(bootProc) {
this.stepperId = null; this.stepperId = null;
this.stepping = false; this.stepping = false;
this.startingFuel = 1000; this.startingFuel = 1000;
this.dataspace = new Dataspace(bootProc); this.dataspace = new Dataspace(this, bootProc);
this.stopHandler = function () {}; this.stopHandlers = [];
this.backgroundTaskCount = 0;
} }
Ground.prototype.start = function () { Ground.prototype.start = function () {
@ -32,8 +33,9 @@ Ground.prototype._step = function () {
if (stillBusy) { if (stillBusy) {
this.start(); this.start();
} else { } else {
if (this.stopHandler) { if (!this.backgroundTaskCount) {
this.stopHandler(this); this.stopHandlers.forEach((h) => h());
this.stopHandlers = [];
} }
} }
} finally { } finally {
@ -48,4 +50,15 @@ Ground.prototype.stop = function () {
} }
}; };
Ground.prototype.addStopHandler = function (h) {
this.stopHandlers.push(h);
};
function bootModule(mod) {
let g = new Ground(() => {
Dataspace.activate(mod.exports);
}).start();
}
module.exports.Ground = Ground; module.exports.Ground = Ground;
module.exports.bootModule = bootModule;

View File

@ -41,3 +41,5 @@ module.exports.Observe = Assertions.Observe;
module.exports.Seal = Assertions.Seal; module.exports.Seal = Assertions.Seal;
module.exports.Inbound = Assertions.Inbound; module.exports.Inbound = Assertions.Inbound;
module.exports.Outbound = Assertions.Outbound; module.exports.Outbound = Assertions.Outbound;
module.exports.bootModule = Ground.bootModule;