makeDataspace -> new Dataspace

This commit is contained in:
Tony Garnock-Jones 2021-02-23 08:52:54 +01:00
parent 4f148b19e7
commit 2846c8cbe0
1 changed files with 45 additions and 47 deletions

92
main.ts
View File

@ -4,54 +4,52 @@ import { Bag, ChangeDescription } from './bag';
const Observe = Record.makeConstructor<Ref<Entity>>('Observe', ['label', 'observer']);
function makeDataspace(): Entity {
const handleMap: IdentityMap<Handle, Record<Ref<Entity>>> = new IdentityMap();
const assertions = new Bag<Ref<Entity>>();
const subscriptions: Dictionary<Map<Ref<Entity>, Dictionary<Handle>>> = new Dictionary();
class Dataspace implements Entity {
readonly handleMap: IdentityMap<Handle, Record<Ref<Entity>>> = new IdentityMap();
readonly assertions = new Bag<Ref<Entity>>();
readonly subscriptions: Dictionary<Map<Ref<Entity>, Dictionary<Handle>>> = new Dictionary();
return {
[assert](turn: Turn, rec: Assertion, handle: Handle): void {
if (!Record.isRecord<Ref<Entity>>(rec)) return;
handleMap.set(handle, rec);
if (assertions.change(rec, +1) !== ChangeDescription.ABSENT_TO_PRESENT) return;
if (Observe.isClassOf(rec)) {
const label = Observe._.label(rec)!;
const observer = Observe._.observer(rec) as Ref<Entity>;
const seen = new Dictionary<Handle>();
if (!subscriptions.has(label)) subscriptions.set(label, new Map());
subscriptions.get(label)!.set(observer, seen);
assertions.forEach((_count, prev) =>
is((prev as Record<Ref<Entity>>).label, label)
&& seen.set(prev, turn.assert(observer, prev)));
}
subscriptions.get(rec.label)?.forEach((seen, peer) =>
seen.has(rec) || seen.set(rec, turn.assert(peer, rec)));
},
[retract](turn: Turn, upstreamHandle: Handle): void {
const rec = handleMap.get(upstreamHandle);
if (rec === void 0) return;
handleMap.delete(upstreamHandle);
if (assertions.change(rec, -1) !== ChangeDescription.PRESENT_TO_ABSENT) return;
subscriptions.get(rec.label)?.forEach((seen, _peer) => {
const downstreamHandle = seen.get(rec);
if (downstreamHandle !== void 0) {
turn.retract(downstreamHandle);
seen.delete(rec);
}
});
if (Observe.isClassOf(rec)) {
let peerMap = subscriptions.get(Observe._.label(rec)!)!;
peerMap.delete(Observe._.observer(rec) as Ref<Entity>);
if (peerMap.size === 0) subscriptions.delete(Observe._.label(rec)!);
}
},
[message](turn: Turn, rec: Assertion): void {
if (!Record.isRecord<Ref<Entity>>(rec)) return;
subscriptions.get(rec.label)?.forEach((_seen, peer) => turn.message(peer, rec));
[assert](turn: Turn, rec: Assertion, handle: Handle): void {
if (!Record.isRecord<Ref<Entity>>(rec)) return;
this.handleMap.set(handle, rec);
if (this.assertions.change(rec, +1) !== ChangeDescription.ABSENT_TO_PRESENT) return;
if (Observe.isClassOf(rec)) {
const label = Observe._.label(rec)!;
const observer = Observe._.observer(rec) as Ref<Entity>;
const seen = new Dictionary<Handle>();
if (!this.subscriptions.has(label)) this.subscriptions.set(label, new Map());
this.subscriptions.get(label)!.set(observer, seen);
this.assertions.forEach((_count, prev) =>
is((prev as Record<Ref<Entity>>).label, label)
&& seen.set(prev, turn.assert(observer, prev)));
}
};
this.subscriptions.get(rec.label)?.forEach((seen, peer) =>
seen.has(rec) || seen.set(rec, turn.assert(peer, rec)));
}
[retract](turn: Turn, upstreamHandle: Handle): void {
const rec = this.handleMap.get(upstreamHandle);
if (rec === void 0) return;
this.handleMap.delete(upstreamHandle);
if (this.assertions.change(rec, -1) !== ChangeDescription.PRESENT_TO_ABSENT) return;
this.subscriptions.get(rec.label)?.forEach((seen, _peer) => {
const downstreamHandle = seen.get(rec);
if (downstreamHandle !== void 0) {
turn.retract(downstreamHandle);
seen.delete(rec);
}
});
if (Observe.isClassOf(rec)) {
let peerMap = this.subscriptions.get(Observe._.label(rec)!)!;
peerMap.delete(Observe._.observer(rec) as Ref<Entity>);
if (peerMap.size === 0) this.subscriptions.delete(Observe._.label(rec)!);
}
}
[message](turn: Turn, rec: Assertion): void {
if (!Record.isRecord<Ref<Entity>>(rec)) return;
this.subscriptions.get(rec.label)?.forEach((_seen, peer) => turn.message(peer, rec));
}
}
const BoxState = Record.makeConstructor<Ref<Entity>>('BoxState', ['value']);
@ -60,7 +58,7 @@ const SetBox = Record.makeConstructor<Ref<Entity>>('SetBox', ['newValue']);
let startTime = Date.now();
let prevValue = 0;
Turn.for(null, async (t: Turn) => {
const ds = new Ref(new Actor(), makeDataspace());
const ds = new Ref(new Actor(), new Dataspace());
// Box
t.spawn(t => {