Tighten and simplify
This commit is contained in:
parent
6a5cac5328
commit
2f3a249ab5
39
actor.ts
39
actor.ts
|
@ -45,21 +45,19 @@ export class Actor {
|
||||||
}
|
}
|
||||||
|
|
||||||
terminateWith(t: Turn, reason: Exclude<ExitReason, null>) {
|
terminateWith(t: Turn, reason: Exclude<ExitReason, null>) {
|
||||||
if (this.alive) {
|
if (!this.alive) return;
|
||||||
this.exitReason = reason;
|
this.exitReason = reason;
|
||||||
this.outbound.forEach((peer, h) => t._retract(peer, h));
|
this.outbound.forEach((peer, h) => t._retract(peer, h));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
execute(proc: () => void): void {
|
execute(proc: () => void): void {
|
||||||
queueMicrotask(() => {
|
queueMicrotask(() => {
|
||||||
if (this.alive) {
|
if (!this.alive) return;
|
||||||
try {
|
try {
|
||||||
proc();
|
proc();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(Actor, err);
|
console.error(Actor, err);
|
||||||
Turn.for(this, t => this.terminateWith(t, { ok: false, err }));
|
Turn.for(this, t => this.terminateWith(t, { ok: false, err }));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -86,9 +84,7 @@ export class Turn {
|
||||||
}
|
}
|
||||||
|
|
||||||
_ensureActor(what: string): Actor {
|
_ensureActor(what: string): Actor {
|
||||||
if (this.actor === null) {
|
if (this.actor === null) throw new Error(`Cannot ${what} from non-Actor context`);
|
||||||
throw new Error(`Cannot ${what} from non-Actor context`);
|
|
||||||
}
|
|
||||||
return this.actor;
|
return this.actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,10 +97,9 @@ export class Turn {
|
||||||
this._ensureActor("spawn with initialAssertions");
|
this._ensureActor("spawn with initialAssertions");
|
||||||
}
|
}
|
||||||
this.localActions.push(() => {
|
this.localActions.push(() => {
|
||||||
const transferred = this.actor === null
|
const child = new Actor(this.actor === null
|
||||||
? void 0
|
? void 0
|
||||||
: extractFromMap(this.actor.outbound, initialAssertions);
|
: extractFromMap(this.actor.outbound, initialAssertions));
|
||||||
const child = new Actor(transferred);
|
|
||||||
child.execute(() => Turn.for(child, bootProc));
|
child.execute(() => Turn.for(child, bootProc));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -155,8 +150,7 @@ export class Turn {
|
||||||
complete(): void {
|
complete(): void {
|
||||||
if (this.completed) throw new Error("Reuse of completed Turn!");
|
if (this.completed) throw new Error("Reuse of completed Turn!");
|
||||||
this.completed = true;
|
this.completed = true;
|
||||||
this.queues.forEach((queue, actor) =>
|
this.queues.forEach((q, a) => a.execute(() => q.forEach(f => Turn.for(a, f))));
|
||||||
actor.execute(() => queue.forEach(f => Turn.for(actor, f))));
|
|
||||||
if (this.localActions.length > 0) {
|
if (this.localActions.length > 0) {
|
||||||
queueMicrotask(() => this.localActions.forEach(f => Turn.for(this.actor, f)));
|
queueMicrotask(() => this.localActions.forEach(f => Turn.for(this.actor, f)));
|
||||||
}
|
}
|
||||||
|
@ -167,11 +161,8 @@ function extractFromMap<K, V>(map: Map<K, V>, keys?: IdentitySet<K>): Map<K, V>
|
||||||
const result: Map<K, V> = new Map();
|
const result: Map<K, V> = new Map();
|
||||||
if (keys !== void 0) {
|
if (keys !== void 0) {
|
||||||
keys.forEach(key => {
|
keys.forEach(key => {
|
||||||
const value = map.get(key);
|
if (map.has(key)) result.set(key, map.get(key)!);
|
||||||
if (value !== void 0) {
|
map.delete(key);
|
||||||
map.delete(key);
|
|
||||||
result.set(key, value);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
14
main.ts
14
main.ts
|
@ -19,10 +19,6 @@ function makeDataspace(): Entity {
|
||||||
const assertions = new Bag<Ref<Entity>>();
|
const assertions = new Bag<Ref<Entity>>();
|
||||||
const subscriptions: Dictionary<Map<Ref<Entity>, Dictionary<Handle>>> = new Dictionary();
|
const subscriptions: Dictionary<Map<Ref<Entity>, Dictionary<Handle>>> = new Dictionary();
|
||||||
|
|
||||||
function forEachSubscription(assertion: Record<Ref<Entity>>, f: (seen: Dictionary<Handle>, peer: Ref<Entity>) => void): void {
|
|
||||||
subscriptions.get(assertion.label)?.forEach(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
[assert](turn: Turn, rec: Assertion, handle: Handle): void {
|
[assert](turn: Turn, rec: Assertion, handle: Handle): void {
|
||||||
if (!Record.isRecord<Ref<Entity>>(rec)) return;
|
if (!Record.isRecord<Ref<Entity>>(rec)) return;
|
||||||
|
@ -38,7 +34,7 @@ function makeDataspace(): Entity {
|
||||||
is((prev as Record<Ref<Entity>>).label, label)
|
is((prev as Record<Ref<Entity>>).label, label)
|
||||||
&& seen.set(prev, turn.assert(observer, prev)));
|
&& seen.set(prev, turn.assert(observer, prev)));
|
||||||
}
|
}
|
||||||
forEachSubscription(rec, (seen, peer) =>
|
subscriptions.get(rec.label)?.forEach((seen, peer) =>
|
||||||
seen.has(rec) || seen.set(rec, turn.assert(peer, rec)));
|
seen.has(rec) || seen.set(rec, turn.assert(peer, rec)));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -47,7 +43,7 @@ function makeDataspace(): Entity {
|
||||||
if (rec === void 0) return;
|
if (rec === void 0) return;
|
||||||
handleMap.delete(upstreamHandle);
|
handleMap.delete(upstreamHandle);
|
||||||
if (assertions.change(rec, -1) !== ChangeDescription.PRESENT_TO_ABSENT) return;
|
if (assertions.change(rec, -1) !== ChangeDescription.PRESENT_TO_ABSENT) return;
|
||||||
forEachSubscription(rec, (seen, _peer) => {
|
subscriptions.get(rec.label)?.forEach((seen, _peer) => {
|
||||||
const downstreamHandle = seen.get(rec);
|
const downstreamHandle = seen.get(rec);
|
||||||
if (downstreamHandle !== void 0) {
|
if (downstreamHandle !== void 0) {
|
||||||
turn.retract(downstreamHandle);
|
turn.retract(downstreamHandle);
|
||||||
|
@ -63,7 +59,7 @@ function makeDataspace(): Entity {
|
||||||
|
|
||||||
[message](turn: Turn, rec: Assertion): void {
|
[message](turn: Turn, rec: Assertion): void {
|
||||||
if (!Record.isRecord<Ref<Entity>>(rec)) return;
|
if (!Record.isRecord<Ref<Entity>>(rec)) return;
|
||||||
forEachSubscription(rec, (_seen, peer) => turn.message(peer, rec));
|
subscriptions.get(rec.label)?.forEach((_seen, peer) => turn.message(peer, rec));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -79,10 +75,8 @@ Turn.for(null, async (t: Turn) => {
|
||||||
// Box
|
// Box
|
||||||
t.spawn(t => {
|
t.spawn(t => {
|
||||||
console.log('Spawning Box');
|
console.log('Spawning Box');
|
||||||
let value: number;
|
|
||||||
let valueHandle: Handle | undefined;
|
let valueHandle: Handle | undefined;
|
||||||
function setValue(t: Turn, newValue: number) {
|
function setValue(t: Turn, value: number) {
|
||||||
value = newValue;
|
|
||||||
valueHandle = t.replace(ds, valueHandle, BoxState(value));
|
valueHandle = t.replace(ds, valueHandle, BoxState(value));
|
||||||
}
|
}
|
||||||
setValue(t, 0);
|
setValue(t, 0);
|
||||||
|
|
Loading…
Reference in New Issue