This commit is contained in:
Tony Garnock-Jones 2021-02-23 10:56:12 +01:00
parent edfc38f811
commit c318aca51a
2 changed files with 12 additions and 20 deletions

View File

@ -68,55 +68,47 @@ let nextHandle = 0;
type LocalAction = (t: Turn) => void; type LocalAction = (t: Turn) => void;
export class Turn { export class Turn {
readonly actor: Actor | null; // whose turn it is to act during this Turn readonly actor: Actor;
readonly queues: Map<Actor, LocalAction[]> = new Map(); readonly queues: Map<Actor, LocalAction[]> = new Map();
readonly localActions: Array<LocalAction> = []; readonly localActions: Array<LocalAction> = [];
completed = false; completed = false;
static for(actor: Actor | null, f: (t: Turn) => void): void { static for(actor: Actor, f: (t: Turn) => void): void {
const t = new Turn(actor); const t = new Turn(actor);
f(t); f(t);
t.complete(); t.complete();
} }
private constructor(actor: Actor | null) { private constructor(actor: Actor) {
this.actor = actor; this.actor = actor;
} }
_ensureActor(what: string): Actor { ref<T>(t: T): Ref<T> {
if (this.actor === null) throw new Error(`Cannot ${what} from non-Actor context`); return new Ref(this.actor, t);
return this.actor;
}
ref<T>(t: T, what: string = "ref"): Ref<T> {
return new Ref(this._ensureActor(what), t);
} }
spawn(bootProc: (t: Turn) => void, initialAssertions = new IdentitySet<Handle>()): void { spawn(bootProc: (t: Turn) => void, initialAssertions = new IdentitySet<Handle>()): void {
if (initialAssertions.size > 0) this._ensureActor("spawn with initialAssertions");
this.localActions.push(() => { this.localActions.push(() => {
const child = new Actor(this.actor === null const child = new Actor(extractFromMap(this.actor.outbound, initialAssertions));
? void 0
: extractFromMap(this.actor.outbound, initialAssertions));
child.execute(() => Turn.for(child, bootProc)); child.execute(() => Turn.for(child, bootProc));
}); });
} }
quit(): void { quit(): void {
this.localActions.push(t => this._ensureActor("quit").terminateWith(t, { ok: true })); this.localActions.push(t => this.actor.terminateWith(t, { ok: true }));
} }
assert(location: Ref<Entity>, assertion: Assertion): Handle { assert(location: Ref<Entity>, assertion: Assertion): Handle {
const h = nextHandle++; const h = nextHandle++;
this.enqueue(location.actor, t => { this.enqueue(location.actor, t => {
this._ensureActor("assert").outbound.set(h, location); this.actor.outbound.set(h, location);
location.target[assert]?.(t, assertion, h); location.target[assert]?.(t, assertion, h);
}); });
return h; return h;
} }
retract(h: Handle): void { retract(h: Handle): void {
this._retract(this._ensureActor("retract").outbound.get(h)!, h); this._retract(this.actor.outbound.get(h)!, h);
} }
replace(location: Ref<Entity>, h: Handle | undefined, assertion: Assertion): Handle { replace(location: Ref<Entity>, h: Handle | undefined, assertion: Assertion): Handle {
@ -127,14 +119,14 @@ export class Turn {
_retract(location: Ref<Entity>, handle: Handle): void { _retract(location: Ref<Entity>, handle: Handle): void {
this.enqueue(location.actor, t => { this.enqueue(location.actor, t => {
this.actor!.outbound.delete(handle); this.actor.outbound.delete(handle);
location.target[retract]?.(t, handle); location.target[retract]?.(t, handle);
}); });
} }
sync(location: Ref<any>): Promise<Turn> { sync(location: Ref<any>): Promise<Turn> {
return new Promise(resolve => return new Promise(resolve =>
this.enqueue(location.actor, t => location.sync(t, this.ref(resolve, "sync")))); this.enqueue(location.actor, t => location.sync(t, this.ref(resolve))));
} }
message(location: Ref<Entity>, assertion: Assertion): void { message(location: Ref<Entity>, assertion: Assertion): void {

View File

@ -58,7 +58,7 @@ const SetBox = Record.makeConstructor<Ref<Entity>>('SetBox', ['newValue']);
let startTime = Date.now(); let startTime = Date.now();
let prevValue = 0; let prevValue = 0;
const LIMIT = 500000; const LIMIT = 500000;
Turn.for(null, async (t: Turn) => { Turn.for(new Actor(), async (t: Turn) => {
const ds = new Ref(new Actor(), new Dataspace()); const ds = new Ref(new Actor(), new Dataspace());
// Box // Box