@ecsia/scheduler 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +32 -0
- package/dist/commands/apply.d.ts +49 -0
- package/dist/commands/apply.d.ts.map +1 -0
- package/dist/commands/apply.js +211 -0
- package/dist/commands/apply.js.map +1 -0
- package/dist/commands/buffer.d.ts +53 -0
- package/dist/commands/buffer.d.ts.map +1 -0
- package/dist/commands/buffer.js +66 -0
- package/dist/commands/buffer.js.map +1 -0
- package/dist/commands/encode.d.ts +30 -0
- package/dist/commands/encode.d.ts.map +1 -0
- package/dist/commands/encode.js +108 -0
- package/dist/commands/encode.js.map +1 -0
- package/dist/commands/fields.d.ts +22 -0
- package/dist/commands/fields.d.ts.map +1 -0
- package/dist/commands/fields.js +123 -0
- package/dist/commands/fields.js.map +1 -0
- package/dist/commands/index.d.ts +10 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +6 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/op.d.ts +16 -0
- package/dist/commands/op.d.ts.map +1 -0
- package/dist/commands/op.js +43 -0
- package/dist/commands/op.js.map +1 -0
- package/dist/executor/guards.d.ts +8 -0
- package/dist/executor/guards.d.ts.map +1 -0
- package/dist/executor/guards.js +61 -0
- package/dist/executor/guards.js.map +1 -0
- package/dist/executor/index.d.ts +9 -0
- package/dist/executor/index.d.ts.map +1 -0
- package/dist/executor/index.js +6 -0
- package/dist/executor/index.js.map +1 -0
- package/dist/executor/run-wave.d.ts +19 -0
- package/dist/executor/run-wave.d.ts.map +1 -0
- package/dist/executor/run-wave.js +38 -0
- package/dist/executor/run-wave.js.map +1 -0
- package/dist/executor/scheduler.d.ts +41 -0
- package/dist/executor/scheduler.d.ts.map +1 -0
- package/dist/executor/scheduler.js +71 -0
- package/dist/executor/scheduler.js.map +1 -0
- package/dist/executor/seams.d.ts +38 -0
- package/dist/executor/seams.d.ts.map +1 -0
- package/dist/executor/seams.js +16 -0
- package/dist/executor/seams.js.map +1 -0
- package/dist/executor/update-threaded.d.ts +17 -0
- package/dist/executor/update-threaded.d.ts.map +1 -0
- package/dist/executor/update-threaded.js +67 -0
- package/dist/executor/update-threaded.js.map +1 -0
- package/dist/executor/update.d.ts +4 -0
- package/dist/executor/update.d.ts.map +1 -0
- package/dist/executor/update.js +23 -0
- package/dist/executor/update.js.map +1 -0
- package/dist/graph/dag.d.ts +16 -0
- package/dist/graph/dag.d.ts.map +1 -0
- package/dist/graph/dag.js +118 -0
- package/dist/graph/dag.js.map +1 -0
- package/dist/graph/edges.d.ts +20 -0
- package/dist/graph/edges.d.ts.map +1 -0
- package/dist/graph/edges.js +181 -0
- package/dist/graph/edges.js.map +1 -0
- package/dist/graph/index.d.ts +8 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +5 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/waves.d.ts +30 -0
- package/dist/graph/waves.d.ts.map +1 -0
- package/dist/graph/waves.js +133 -0
- package/dist/graph/waves.js.map +1 -0
- package/dist/graph/weights.d.ts +7 -0
- package/dist/graph/weights.d.ts.map +1 -0
- package/dist/graph/weights.js +10 -0
- package/dist/graph/weights.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +13 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +12 -0
- package/dist/internal.js.map +1 -0
- package/dist/planner/access.d.ts +18 -0
- package/dist/planner/access.d.ts.map +1 -0
- package/dist/planner/access.js +92 -0
- package/dist/planner/access.js.map +1 -0
- package/dist/planner/define-system.d.ts +14 -0
- package/dist/planner/define-system.d.ts.map +1 -0
- package/dist/planner/define-system.js +30 -0
- package/dist/planner/define-system.js.map +1 -0
- package/dist/planner/index.d.ts +6 -0
- package/dist/planner/index.d.ts.map +1 -0
- package/dist/planner/index.js +4 -0
- package/dist/planner/index.js.map +1 -0
- package/dist/planner/types.d.ts +74 -0
- package/dist/planner/types.d.ts.map +1 -0
- package/dist/planner/types.js +6 -0
- package/dist/planner/types.js.map +1 -0
- package/dist/workers/atomics-shim.d.ts +8 -0
- package/dist/workers/atomics-shim.d.ts.map +1 -0
- package/dist/workers/atomics-shim.js +14 -0
- package/dist/workers/atomics-shim.js.map +1 -0
- package/dist/workers/index.d.ts +13 -0
- package/dist/workers/index.d.ts.map +1 -0
- package/dist/workers/index.js +10 -0
- package/dist/workers/index.js.map +1 -0
- package/dist/workers/manifest.d.ts +67 -0
- package/dist/workers/manifest.d.ts.map +1 -0
- package/dist/workers/manifest.js +5 -0
- package/dist/workers/manifest.js.map +1 -0
- package/dist/workers/pool.d.ts +60 -0
- package/dist/workers/pool.d.ts.map +1 -0
- package/dist/workers/pool.js +313 -0
- package/dist/workers/pool.js.map +1 -0
- package/dist/workers/reservation.d.ts +18 -0
- package/dist/workers/reservation.d.ts.map +1 -0
- package/dist/workers/reservation.js +41 -0
- package/dist/workers/reservation.js.map +1 -0
- package/dist/workers/wave-sync.d.ts +18 -0
- package/dist/workers/wave-sync.d.ts.map +1 -0
- package/dist/workers/wave-sync.js +88 -0
- package/dist/workers/wave-sync.js.map +1 -0
- package/dist/workers/worker-entry.d.ts +2 -0
- package/dist/workers/worker-entry.d.ts.map +1 -0
- package/dist/workers/worker-entry.js +187 -0
- package/dist/workers/worker-entry.js.map +1 -0
- package/dist/workers/worker-system.d.ts +31 -0
- package/dist/workers/worker-system.d.ts.map +1 -0
- package/dist/workers/worker-system.js +20 -0
- package/dist/workers/worker-system.js.map +1 -0
- package/dist/workers/world-view.d.ts +39 -0
- package/dist/workers/world-view.d.ts.map +1 -0
- package/dist/workers/world-view.js +85 -0
- package/dist/workers/world-view.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// Wave extraction + type-level conflict detection v1 + batch packing. The reduced
|
|
2
|
+
// DAG is layered into waves (Kahn by in-degree); within a wave, two systems may run concurrently iff
|
|
3
|
+
// their access is DISJOINT at component-type granularity (WAVE-CONFLICT). This is the explicit
|
|
4
|
+
// REJECTION of becsy lane-merging: readers of a component run concurrently.
|
|
5
|
+
/**
|
|
6
|
+
* Rule WAVE-CONFLICT (v1, T5): A and B are concurrency-compatible iff write-sets
|
|
7
|
+
* are disjoint AND neither writes what the other reads. Pure read–read overlap is allowed.
|
|
8
|
+
* O(accessStrideWords) per pair — never per-entity, never per-archetype. This is the single seam a v2
|
|
9
|
+
* column-level build narrows.
|
|
10
|
+
*/
|
|
11
|
+
export function concurrencyCompatible(a, b) {
|
|
12
|
+
const n = a.writeWords.length;
|
|
13
|
+
for (let w = 0; w < n; w++) {
|
|
14
|
+
const aw = a.writeWords[w];
|
|
15
|
+
const bw = b.writeWords[w];
|
|
16
|
+
if (aw & bw)
|
|
17
|
+
return false; // write/write
|
|
18
|
+
if (aw & b.readWords[w])
|
|
19
|
+
return false; // a-write / b-read
|
|
20
|
+
if (a.readWords[w] & bw)
|
|
21
|
+
return false; // a-read / b-write
|
|
22
|
+
}
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
/**: topological layering by in-degree (Kahn). Deterministic intra-wave order: SystemId asc. */
|
|
26
|
+
function extractWaves(dag) {
|
|
27
|
+
const n = dag.n;
|
|
28
|
+
const indeg = new Int32Array(n);
|
|
29
|
+
for (let u = 0; u < n; u++) {
|
|
30
|
+
for (const v of dag.succ[u])
|
|
31
|
+
indeg[v] += 1;
|
|
32
|
+
}
|
|
33
|
+
let ready = [];
|
|
34
|
+
for (let i = 0; i < n; i++)
|
|
35
|
+
if (indeg[i] === 0)
|
|
36
|
+
ready.push(i);
|
|
37
|
+
const waves = [];
|
|
38
|
+
let placed = 0;
|
|
39
|
+
while (ready.length > 0) {
|
|
40
|
+
ready.sort((a, b) => a - b); // deterministic order within a wave
|
|
41
|
+
const wave = ready.map((i) => i);
|
|
42
|
+
waves.push(wave);
|
|
43
|
+
placed += wave.length;
|
|
44
|
+
const next = [];
|
|
45
|
+
for (const u of ready) {
|
|
46
|
+
for (const v of dag.succ[u]) {
|
|
47
|
+
const vn = v;
|
|
48
|
+
if (--indeg[vn] === 0)
|
|
49
|
+
next.push(vn);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
ready = next;
|
|
53
|
+
}
|
|
54
|
+
if (placed !== n) {
|
|
55
|
+
// A cycle slipped through — impossible after dag.ts cycle detection, but assert for safety.
|
|
56
|
+
throw new Error(`wave extraction dropped systems (${placed}/${n}); a cycle escaped detection`);
|
|
57
|
+
}
|
|
58
|
+
return waves;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
*: partition a wave's systems into sequential rounds via greedy graph coloring over the
|
|
62
|
+
* incompatibility graph (`A—B` iff !concurrencyCompatible). Worker-ineligible systems are pinned to a
|
|
63
|
+
* main-thread slot (workerIndex -1); each round holds at most one main-thread slot.
|
|
64
|
+
*/
|
|
65
|
+
function packWave(wave, systems, workers) {
|
|
66
|
+
const rounds = [];
|
|
67
|
+
const perWorkerSpawn = new Uint32Array(Math.max(workers, 0));
|
|
68
|
+
for (const id of wave) {
|
|
69
|
+
const sb = systems[id];
|
|
70
|
+
let placed = false;
|
|
71
|
+
for (const round of rounds) {
|
|
72
|
+
const compatible = round.boxes.every((other) => concurrencyCompatible(sb, other));
|
|
73
|
+
if (!compatible)
|
|
74
|
+
continue;
|
|
75
|
+
if (sb.workerEligible) {
|
|
76
|
+
// Eligible system: assign to a worker slot if any worker exists, else the main-thread slot.
|
|
77
|
+
if (workers > 0 && round.nextWorker < workers) {
|
|
78
|
+
const wi = round.nextWorker;
|
|
79
|
+
round.nextWorker += 1;
|
|
80
|
+
round.members.push({ systemId: id, workerIndex: wi });
|
|
81
|
+
round.boxes.push(sb);
|
|
82
|
+
if (workers > 0)
|
|
83
|
+
perWorkerSpawn[wi] += sb.maxSpawnsPerWave;
|
|
84
|
+
placed = true;
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
if (workers === 0 && !round.hasMainThreadSlot) {
|
|
88
|
+
round.hasMainThreadSlot = true;
|
|
89
|
+
round.members.push({ systemId: id, workerIndex: -1 });
|
|
90
|
+
round.boxes.push(sb);
|
|
91
|
+
placed = true;
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else if (!round.hasMainThreadSlot) {
|
|
96
|
+
// Ineligible system: only the single main-thread slot per round.
|
|
97
|
+
round.hasMainThreadSlot = true;
|
|
98
|
+
round.members.push({ systemId: id, workerIndex: -1 });
|
|
99
|
+
round.boxes.push(sb);
|
|
100
|
+
placed = true;
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (!placed) {
|
|
105
|
+
const wi = sb.workerEligible && workers > 0 ? 0 : -1;
|
|
106
|
+
const round = {
|
|
107
|
+
members: [{ systemId: id, workerIndex: wi }],
|
|
108
|
+
boxes: [sb],
|
|
109
|
+
hasMainThreadSlot: wi === -1,
|
|
110
|
+
nextWorker: wi === -1 ? 0 : 1,
|
|
111
|
+
};
|
|
112
|
+
if (wi >= 0)
|
|
113
|
+
perWorkerSpawn[wi] += sb.maxSpawnsPerWave;
|
|
114
|
+
rounds.push(round);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
rounds: rounds.map((r) => r.members),
|
|
119
|
+
perWorkerSpawnHint: perWorkerSpawn,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/** Build the immutable SchedulePlan from the reduced DAG. */
|
|
123
|
+
export function buildPlan(systems, dag, accessStrideWords, workers) {
|
|
124
|
+
const waveIds = extractWaves(dag);
|
|
125
|
+
const waves = waveIds.map((wave) => packWave(wave, systems, workers));
|
|
126
|
+
return Object.freeze({
|
|
127
|
+
waves,
|
|
128
|
+
systems,
|
|
129
|
+
accessStrideWords,
|
|
130
|
+
workers,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=waves.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"waves.js","sourceRoot":"","sources":["../../src/graph/waves.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const enum EdgeWeight {
|
|
2
|
+
EXPLICIT = 5,// before/after — user-declared, never overridden
|
|
3
|
+
DENY = 4,// inAnyOrderWith(A,B) — suppresses an IMPLICIT edge between A,B
|
|
4
|
+
CLASS_HINT = 3,// beforeWritersOf(C) / afterReadersOf(C)
|
|
5
|
+
IMPLICIT = 1
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=weights.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weights.d.ts","sourceRoot":"","sources":["../../src/graph/weights.ts"],"names":[],"mappings":"AAGA,0BAAkB,UAAU;IAC1B,QAAQ,IAAI,CAAE,iDAAiD;IAC/D,IAAI,IAAI,CAAE,gEAAgE;IAC1E,UAAU,IAAI,CAAE,yCAAyC;IACzD,QAAQ,IAAI;CACb"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Priority-weighted conflict-edge scheme (becsy weight scheme). Highest weight
|
|
2
|
+
// wins for an ordered pair; a DENY removes the IMPLICIT edge only (it cannot remove a 3/5 edge).
|
|
3
|
+
export var EdgeWeight;
|
|
4
|
+
(function (EdgeWeight) {
|
|
5
|
+
EdgeWeight[EdgeWeight["EXPLICIT"] = 5] = "EXPLICIT";
|
|
6
|
+
EdgeWeight[EdgeWeight["DENY"] = 4] = "DENY";
|
|
7
|
+
EdgeWeight[EdgeWeight["CLASS_HINT"] = 3] = "CLASS_HINT";
|
|
8
|
+
EdgeWeight[EdgeWeight["IMPLICIT"] = 1] = "IMPLICIT";
|
|
9
|
+
})(EdgeWeight || (EdgeWeight = {}));
|
|
10
|
+
//# sourceMappingURL=weights.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weights.js","sourceRoot":"","sources":["../../src/graph/weights.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,iGAAiG;AAEjG,MAAM,CAAN,IAAkB,UAKjB;AALD,WAAkB,UAAU;IAC1B,mDAAY,CAAA;IACZ,2CAAQ,CAAA;IACR,uDAAc,CAAA;IACd,mDAAY,CAAA;AACd,CAAC,EALiB,UAAU,KAAV,UAAU,QAK3B"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { defineSystem, inAnyOrderWith, beforeWritersOf, afterReadersOf } from './planner/index.js';
|
|
2
|
+
export type { SystemDef, SystemContext, OrderingHint } from './planner/index.js';
|
|
3
|
+
export { createScheduler } from './executor/index.js';
|
|
4
|
+
export type { SchedulerHandle, CreateSchedulerOptions, RoundDispatcher } from './executor/index.js';
|
|
5
|
+
export type { SchedulePlan, ScheduleWave, SystemBatch } from './graph/index.js';
|
|
6
|
+
export type { SystemBox } from './planner/index.js';
|
|
7
|
+
export { WorkerPool } from './workers/index.js';
|
|
8
|
+
export type { PoolConfig, PoolSystem } from './workers/index.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAClG,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAGhF,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACrD,YAAY,EAAE,eAAe,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAQnG,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC/E,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAGnD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC/C,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// @ecsia/scheduler — the system access graph (read/write declarations → conflict DAG), wave-level
|
|
2
|
+
// topological layering with type-level conflict detection (v1), the CORRECT single-threaded executor
|
|
3
|
+
// (wave order + serial slots for command-buffer flush and deferred observers), the world.update()
|
|
4
|
+
// frame loop, and the parallel-READY seams (worker dispatch + Atomics wave-sync). DEPENDS ON
|
|
5
|
+
// @ecsia/core; @ecsia/core NEVER imports this package (acyclic: schema ← core ← scheduler).
|
|
6
|
+
//
|
|
7
|
+
// The kernel runs single-threaded WITHOUT this module; the scheduler is an opt-in layer
|
|
8
|
+
// Importing it + `createScheduler(world, systems).update(dt)` pulls in the DAG +
|
|
9
|
+
// waves; nothing else changes for the user.
|
|
10
|
+
//
|
|
11
|
+
// PUBLIC SURFACE ONLY. The DAG/wave builders, command-buffer encoder, executor
|
|
12
|
+
// run loop, and worker SAB primitives are implementation internals — they live in `./internal.ts`,
|
|
13
|
+
// are NOT re-exported here, and are reached by this package's own tests through a relative import.
|
|
14
|
+
// The umbrella (ecsia) re-exports exactly the symbols below.
|
|
15
|
+
// --- planner: the system descriptor + ordering hints ---
|
|
16
|
+
export { defineSystem, inAnyOrderWith, beforeWritersOf, afterReadersOf } from './planner/index.js';
|
|
17
|
+
// --- executor: the opt-in frame scheduler ---
|
|
18
|
+
export { createScheduler } from './executor/index.js';
|
|
19
|
+
// --- workers: the worker pool the threaded frame loop drives ---
|
|
20
|
+
export { WorkerPool } from './workers/index.js';
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,qGAAqG;AACrG,kGAAkG;AAClG,6FAA6F;AAC7F,4FAA4F;AAC5F,EAAE;AACF,wFAAwF;AACxF,iFAAiF;AACjF,4CAA4C;AAC5C,EAAE;AACF,+EAA+E;AAC/E,mGAAmG;AACnG,mGAAmG;AACnG,6DAA6D;AAE7D,0DAA0D;AAC1D,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAGlG,+CAA+C;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAYrD,kEAAkE;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { lowerSystems, aggregateAccess, DEFAULT_MAX_SPAWNS_PER_WAVE } from './planner/index.js';
|
|
2
|
+
export type { SystemBox, AccessMaps } from './planner/index.js';
|
|
3
|
+
export { EdgeWeight, resolveOrdering, buildEdges, buildDAG, CycleError, buildPlan, concurrencyCompatible, } from './graph/index.js';
|
|
4
|
+
export type { Edge, DAG, SchedulePlan, ScheduleWave, SystemBatch } from './graph/index.js';
|
|
5
|
+
export { buildSchedulePlan, runUpdate, runUpdateThreaded, runWave, buildScopedQueries, makeScopedQuery, } from './executor/index.js';
|
|
6
|
+
export type { ExecutorEnv } from './executor/index.js';
|
|
7
|
+
export { selectWaitTier } from './executor/seams.js';
|
|
8
|
+
export type { WorkerMode, WaveSync, WaveCounter, WaveSyncTier, WaveSyncTierProbe, WorkerHandle, WorkerDispatch, } from './executor/seams.js';
|
|
9
|
+
export { Op, recordLen, directApplySink, flushAll, makeCommandBuffer, resetBuffer, ensureWords, makeEncoder, buildFieldCodec, } from './commands/index.js';
|
|
10
|
+
export type { CommandSink, StructuralIntent, WorldApply, CommandBuffer, BufferReservation, CommandEncoder, ComponentEncodeInfo, EncoderEnv, ComponentFieldCodec, } from './commands/index.js';
|
|
11
|
+
export { makeWaveCounter, makeWaveSync, completeWave, setWaveError, waveErrored, workerHead, makeReservationSab, fillReservation, takeReserved, consumedCount, buildWorkerWorldView, matchComponentsOf, hasWaitAsync, waitAsync, } from './workers/index.js';
|
|
12
|
+
export type { WorkerReservationSab, WorkerWorldView, WorkerSystemDef, WorkerSystemKernel, WorkerSystemBox, WorkerBootstrap, ComponentManifestEntry, DispatchMessage, WaitAsyncResult, } from './workers/index.js';
|
|
13
|
+
//# sourceMappingURL=internal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAA;AAC/F,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAE/D,OAAO,EACL,UAAU,EACV,eAAe,EACf,UAAU,EACV,QAAQ,EACR,UAAU,EACV,SAAS,EACT,qBAAqB,GACtB,MAAM,kBAAkB,CAAA;AACzB,YAAY,EAAE,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE1F,OAAO,EACL,iBAAiB,EACjB,SAAS,EACT,iBAAiB,EACjB,OAAO,EACP,kBAAkB,EAClB,eAAe,GAChB,MAAM,qBAAqB,CAAA;AAC5B,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,YAAY,EACV,UAAU,EACV,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,cAAc,GACf,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EACL,EAAE,EACF,SAAS,EACT,eAAe,EACf,QAAQ,EACR,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,WAAW,EACX,eAAe,GAChB,MAAM,qBAAqB,CAAA;AAC5B,YAAY,EACV,WAAW,EACX,gBAAgB,EAChB,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,mBAAmB,EACnB,UAAU,EACV,mBAAmB,GACpB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EACL,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,UAAU,EACV,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,SAAS,GACV,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EACV,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,sBAAsB,EACtB,eAAe,EACf,eAAe,GAChB,MAAM,oBAAoB,CAAA"}
|
package/dist/internal.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// @ecsia/scheduler — INTERNAL surface. NOT part of the published package (`package.json#exports` only
|
|
2
|
+
// maps `.` → index.ts). These are builders/primitives consumed by this package's own tests via a
|
|
3
|
+
// RELATIVE import (`../src/internal.js`); they are deliberately kept OFF the public `index.ts` so the
|
|
4
|
+
// published surface stays curated. No sibling package imports `@ecsia/scheduler`,
|
|
5
|
+
// so nothing here is cross-package — it is test-reachable internals only.
|
|
6
|
+
export { lowerSystems, aggregateAccess, DEFAULT_MAX_SPAWNS_PER_WAVE } from './planner/index.js';
|
|
7
|
+
export { EdgeWeight, resolveOrdering, buildEdges, buildDAG, CycleError, buildPlan, concurrencyCompatible, } from './graph/index.js';
|
|
8
|
+
export { buildSchedulePlan, runUpdate, runUpdateThreaded, runWave, buildScopedQueries, makeScopedQuery, } from './executor/index.js';
|
|
9
|
+
export { selectWaitTier } from './executor/seams.js';
|
|
10
|
+
export { Op, recordLen, directApplySink, flushAll, makeCommandBuffer, resetBuffer, ensureWords, makeEncoder, buildFieldCodec, } from './commands/index.js';
|
|
11
|
+
export { makeWaveCounter, makeWaveSync, completeWave, setWaveError, waveErrored, workerHead, makeReservationSab, fillReservation, takeReserved, consumedCount, buildWorkerWorldView, matchComponentsOf, hasWaitAsync, waitAsync, } from './workers/index.js';
|
|
12
|
+
//# sourceMappingURL=internal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,sGAAsG;AACtG,iGAAiG;AACjG,sGAAsG;AACtG,kFAAkF;AAClF,0EAA0E;AAE1E,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAA;AAG/F,OAAO,EACL,UAAU,EACV,eAAe,EACf,UAAU,EACV,QAAQ,EACR,UAAU,EACV,SAAS,EACT,qBAAqB,GACtB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EACL,iBAAiB,EACjB,SAAS,EACT,iBAAiB,EACjB,OAAO,EACP,kBAAkB,EAClB,eAAe,GAChB,MAAM,qBAAqB,CAAA;AAG5B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAWpD,OAAO,EACL,EAAE,EACF,SAAS,EACT,eAAe,EACf,QAAQ,EACR,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,WAAW,EACX,eAAe,GAChB,MAAM,qBAAqB,CAAA;AAa5B,OAAO,EACL,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,UAAU,EACV,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,SAAS,GACV,MAAM,oBAAoB,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ComponentId, SystemId } from '@ecsia/schema';
|
|
2
|
+
import type { SystemBox, SystemDef } from './types.js';
|
|
3
|
+
export interface AccessMaps {
|
|
4
|
+
/** Who reads each id. */
|
|
5
|
+
readonly readers: Map<ComponentId, Set<SystemId>>;
|
|
6
|
+
/** Who writes each id. */
|
|
7
|
+
readonly writers: Map<ComponentId, Set<SystemId>>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Lower the registered SystemDefs into immutable SystemBoxes. `strideWords` is the single canonical
|
|
11
|
+
* fixed-component-id width (= accessStrideWords = ceil(registeredComponentCount/32)) shared with
|
|
12
|
+
* the bitmask and registry; it does NOT add a separate `+ numRelations` term ( C4)
|
|
13
|
+
* because presence ids are already counted.
|
|
14
|
+
*/
|
|
15
|
+
export declare function lowerSystems(defs: readonly SystemDef[], strideWords: number): SystemBox[];
|
|
16
|
+
/** Aggregate the per-id reader/writer sets from the lowered systems' declared access only. */
|
|
17
|
+
export declare function aggregateAccess(systems: readonly SystemBox[]): AccessMaps;
|
|
18
|
+
//# sourceMappingURL=access.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access.d.ts","sourceRoot":"","sources":["../../src/planner/access.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAgB,WAAW,EAAU,QAAQ,EAAE,MAAM,eAAe,CAAA;AAEhF,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAEtD,MAAM,WAAW,UAAU;IACzB,yBAAyB;IACzB,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAA;IACjD,0BAA0B;IAC1B,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAA;CAClD;AA0CD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,CAoBzF;AAED,8FAA8F;AAC9F,wBAAgB,eAAe,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,GAAG,UAAU,CAgBzE"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// System registration & access aggregation. Lowers each declared `SystemDef` into
|
|
2
|
+
// an immutable `SystemBox`, resolving the declared `{read,write}` ComponentDefs to dense ComponentIds
|
|
3
|
+
// and packing them into fixed-width access signature words for the O(words) disjointness test.
|
|
4
|
+
//
|
|
5
|
+
// Pair IDs are component IDs: a declared read/write of a relation expands to the relation's
|
|
6
|
+
// presence id, an ordinary ComponentId in the same dense space. The defs a user passes carry their
|
|
7
|
+
// registered `.id` already, so resolution here is a `.id` read — no registry handle required.
|
|
8
|
+
import { DEFAULT_MAX_SPAWNS_PER_WAVE } from './types.js';
|
|
9
|
+
const UNREGISTERED = -1;
|
|
10
|
+
function idOf(def) {
|
|
11
|
+
const id = def.id;
|
|
12
|
+
if (id === UNREGISTERED) {
|
|
13
|
+
throw new Error(`system declares access to component '${def.name}' which is not registered with this world`);
|
|
14
|
+
}
|
|
15
|
+
return id;
|
|
16
|
+
}
|
|
17
|
+
/** Sorted-ascending, de-duped ComponentIds for a declared access set. */
|
|
18
|
+
function resolveIds(defs) {
|
|
19
|
+
if (defs === undefined || defs.length === 0)
|
|
20
|
+
return [];
|
|
21
|
+
const seen = new Set();
|
|
22
|
+
for (const def of defs)
|
|
23
|
+
seen.add(idOf(def));
|
|
24
|
+
return [...seen].sort((a, b) => a - b);
|
|
25
|
+
}
|
|
26
|
+
/** A system is worker-ineligible if any declared component carries a non-shareable (object) field. */
|
|
27
|
+
function computeWorkerEligible(def) {
|
|
28
|
+
const all = [...(def.read ?? []), ...(def.write ?? [])];
|
|
29
|
+
for (const c of all) {
|
|
30
|
+
for (const f of c.fields) {
|
|
31
|
+
if (!f.shareable)
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
function packWords(ids, strideWords) {
|
|
38
|
+
const words = new Uint32Array(strideWords);
|
|
39
|
+
for (const c of ids) {
|
|
40
|
+
const i = c;
|
|
41
|
+
words[i >>> 5] = (words[i >>> 5] | (1 << (i & 31))) >>> 0;
|
|
42
|
+
}
|
|
43
|
+
return words;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Lower the registered SystemDefs into immutable SystemBoxes. `strideWords` is the single canonical
|
|
47
|
+
* fixed-component-id width (= accessStrideWords = ceil(registeredComponentCount/32)) shared with
|
|
48
|
+
* the bitmask and registry; it does NOT add a separate `+ numRelations` term ( C4)
|
|
49
|
+
* because presence ids are already counted.
|
|
50
|
+
*/
|
|
51
|
+
export function lowerSystems(defs, strideWords) {
|
|
52
|
+
return defs.map((def, i) => {
|
|
53
|
+
const readIds = resolveIds(def.read);
|
|
54
|
+
const writeIds = resolveIds(def.write);
|
|
55
|
+
return Object.freeze({
|
|
56
|
+
id: i,
|
|
57
|
+
name: def.name,
|
|
58
|
+
def,
|
|
59
|
+
run: def.run,
|
|
60
|
+
readIds,
|
|
61
|
+
writeIds,
|
|
62
|
+
readWords: packWords(readIds, strideWords),
|
|
63
|
+
writeWords: packWords(writeIds, strideWords),
|
|
64
|
+
// `before`/`after` resolved to SystemIds in graph/edges.ts (needs the full id map).
|
|
65
|
+
before: [],
|
|
66
|
+
after: [],
|
|
67
|
+
maxSpawnsPerWave: def.maxSpawnsPerWave ?? DEFAULT_MAX_SPAWNS_PER_WAVE,
|
|
68
|
+
workerEligible: computeWorkerEligible(def),
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/** Aggregate the per-id reader/writer sets from the lowered systems' declared access only. */
|
|
73
|
+
export function aggregateAccess(systems) {
|
|
74
|
+
const readers = new Map();
|
|
75
|
+
const writers = new Map();
|
|
76
|
+
const getOrInit = (m, c) => {
|
|
77
|
+
let s = m.get(c);
|
|
78
|
+
if (s === undefined) {
|
|
79
|
+
s = new Set();
|
|
80
|
+
m.set(c, s);
|
|
81
|
+
}
|
|
82
|
+
return s;
|
|
83
|
+
};
|
|
84
|
+
for (const sb of systems) {
|
|
85
|
+
for (const c of sb.readIds)
|
|
86
|
+
getOrInit(readers, c).add(sb.id);
|
|
87
|
+
for (const c of sb.writeIds)
|
|
88
|
+
getOrInit(writers, c).add(sb.id);
|
|
89
|
+
}
|
|
90
|
+
return { readers, writers };
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=access.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access.js","sourceRoot":"","sources":["../../src/planner/access.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ComponentDef, Schema } from '@ecsia/schema';
|
|
2
|
+
import type { OrderingHint, SystemDef } from './types.js';
|
|
3
|
+
export declare function defineSystem(def: SystemDef): SystemDef;
|
|
4
|
+
/**
|
|
5
|
+
* Records a DENY (weight 4): suppress any IMPLICIT (weight 1) edge between `a` and `b` in both
|
|
6
|
+
* directions ("no implicit edge between these — the user knows it is safe"). Does NOT override an
|
|
7
|
+
* EXPLICIT (5) edge.
|
|
8
|
+
*/
|
|
9
|
+
export declare function inAnyOrderWith(a: SystemDef, b: SystemDef): OrderingHint;
|
|
10
|
+
/** CLASS_HINT (weight 3): this system runs before all current writers of `c`. */
|
|
11
|
+
export declare function beforeWritersOf(c: ComponentDef<Schema>): OrderingHint;
|
|
12
|
+
/** CLASS_HINT (weight 3): this system runs after all current readers of `c`. */
|
|
13
|
+
export declare function afterReadersOf(c: ComponentDef<Schema>): OrderingHint;
|
|
14
|
+
//# sourceMappingURL=define-system.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-system.d.ts","sourceRoot":"","sources":["../../src/planner/define-system.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAEzD,wBAAgB,YAAY,CAAC,GAAG,EAAE,SAAS,GAAG,SAAS,CAQtD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,GAAG,YAAY,CAEvE;AAED,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,GAAG,YAAY,CAErE;AAED,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,GAAG,YAAY,CAEpE"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// `defineSystem` + the ordering-hint combinators. `defineSystem` is
|
|
2
|
+
// identity + light validation; it returns a branded SystemDef the scheduler consumes. The scheduler
|
|
3
|
+
// never infers write-intent from runtime `entity.write(C)` calls — `read`/`write` here is the sole
|
|
4
|
+
// conflict-detection source.
|
|
5
|
+
export function defineSystem(def) {
|
|
6
|
+
if (typeof def.name !== 'string' || def.name.length === 0) {
|
|
7
|
+
throw new Error('defineSystem: `name` is required and must be a non-empty string');
|
|
8
|
+
}
|
|
9
|
+
if (typeof def.run !== 'function') {
|
|
10
|
+
throw new Error(`defineSystem('${def.name}'): \`run\` must be a function`);
|
|
11
|
+
}
|
|
12
|
+
return Object.freeze({ ...def, __ecsiaSystem: true });
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Records a DENY (weight 4): suppress any IMPLICIT (weight 1) edge between `a` and `b` in both
|
|
16
|
+
* directions ("no implicit edge between these — the user knows it is safe"). Does NOT override an
|
|
17
|
+
* EXPLICIT (5) edge.
|
|
18
|
+
*/
|
|
19
|
+
export function inAnyOrderWith(a, b) {
|
|
20
|
+
return { kind: 'deny', a, b };
|
|
21
|
+
}
|
|
22
|
+
/** CLASS_HINT (weight 3): this system runs before all current writers of `c`. */
|
|
23
|
+
export function beforeWritersOf(c) {
|
|
24
|
+
return { kind: 'beforeWritersOf', component: c };
|
|
25
|
+
}
|
|
26
|
+
/** CLASS_HINT (weight 3): this system runs after all current readers of `c`. */
|
|
27
|
+
export function afterReadersOf(c) {
|
|
28
|
+
return { kind: 'afterReadersOf', component: c };
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=define-system.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-system.js","sourceRoot":"","sources":["../../src/planner/define-system.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,oGAAoG;AACpG,mGAAmG;AACnG,6BAA6B;AAK7B,MAAM,UAAU,YAAY,CAAC,GAAc;IACzC,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAA;IACpF,CAAC;IACD,IAAI,OAAO,GAAG,CAAC,GAAG,KAAK,UAAU,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,iBAAiB,GAAG,CAAC,IAAI,gCAAgC,CAAC,CAAA;IAC5E,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,GAAG,EAAE,aAAa,EAAE,IAAa,EAAE,CAAC,CAAA;AAChE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,CAAY,EAAE,CAAY;IACvD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAA;AAC/B,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,eAAe,CAAC,CAAuB;IACrD,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,SAAS,EAAE,CAAC,EAAE,CAAA;AAClD,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,cAAc,CAAC,CAAuB;IACpD,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,SAAS,EAAE,CAAC,EAAE,CAAA;AACjD,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { defineSystem, inAnyOrderWith, beforeWritersOf, afterReadersOf } from './define-system.js';
|
|
2
|
+
export { lowerSystems, aggregateAccess } from './access.js';
|
|
3
|
+
export type { AccessMaps } from './access.js';
|
|
4
|
+
export { DEFAULT_MAX_SPAWNS_PER_WAVE } from './types.js';
|
|
5
|
+
export type { SystemDef, SystemContext, SystemBox, OrderingHint } from './types.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/planner/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAClG,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC3D,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAA;AACxD,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/planner/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAClG,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAE3D,OAAO,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { ComponentDef, ComponentId, Schema, SystemId, Tick } from '@ecsia/schema';
|
|
2
|
+
import type { World } from '@ecsia/core';
|
|
3
|
+
/** The context a system body receives each tick. */
|
|
4
|
+
export interface SystemContext {
|
|
5
|
+
readonly world: World;
|
|
6
|
+
readonly dt: number;
|
|
7
|
+
readonly tick: Tick;
|
|
8
|
+
/** The same `query()` the world exposes, scoped (dev-mode access-guarded) for the wave. */
|
|
9
|
+
readonly query: World['query'];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* An ordering hint produced by `inAnyOrderWith` / `beforeWritersOf` / `afterReadersOf`. These
|
|
13
|
+
* are passed in `SystemDef.order` (ecsia's surface for the becsy weight scheme) and resolved against
|
|
14
|
+
* the registered systems at plan time.
|
|
15
|
+
*/
|
|
16
|
+
export type OrderingHint = {
|
|
17
|
+
readonly kind: 'deny';
|
|
18
|
+
readonly a: SystemDef;
|
|
19
|
+
readonly b: SystemDef;
|
|
20
|
+
} | {
|
|
21
|
+
readonly kind: 'beforeWritersOf';
|
|
22
|
+
readonly component: ComponentDef<Schema>;
|
|
23
|
+
} | {
|
|
24
|
+
readonly kind: 'afterReadersOf';
|
|
25
|
+
readonly component: ComponentDef<Schema>;
|
|
26
|
+
};
|
|
27
|
+
export interface SystemDef {
|
|
28
|
+
readonly name: string;
|
|
29
|
+
/** Declared read access — scheduler conflict input. */
|
|
30
|
+
readonly read?: readonly ComponentDef<Schema>[];
|
|
31
|
+
/** Declared write access — the SOLE source of write-intent. */
|
|
32
|
+
readonly write?: readonly ComponentDef<Schema>[];
|
|
33
|
+
/** Explicit ordering: this runs BEFORE these (EdgeWeight.EXPLICIT = 5). */
|
|
34
|
+
readonly before?: readonly SystemDef[];
|
|
35
|
+
/** Explicit ordering: this runs AFTER these. */
|
|
36
|
+
readonly after?: readonly SystemDef[];
|
|
37
|
+
/** Coarse hints + denial edges. */
|
|
38
|
+
readonly order?: readonly OrderingHint[];
|
|
39
|
+
/** Reservation sizing for OP_CREATE mid-wave (default 64). */
|
|
40
|
+
readonly maxSpawnsPerWave?: number;
|
|
41
|
+
readonly run: (ctx: SystemContext) => void;
|
|
42
|
+
/** Branding marker so a plain object can't be mistaken for a validated SystemDef. */
|
|
43
|
+
readonly __ecsiaSystem?: true;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The internal lowered form. Immutable, declaration-derived ONLY: all
|
|
47
|
+
* plan-derived state lives in the separate `SchedulePlan` so it never goes stale across re-plans
|
|
48
|
+
* (report "Planner metadata on SystemBox mutable fields — stale across re-plans (HMR)").
|
|
49
|
+
*/
|
|
50
|
+
export interface SystemBox {
|
|
51
|
+
readonly id: SystemId;
|
|
52
|
+
readonly name: string;
|
|
53
|
+
readonly def: SystemDef;
|
|
54
|
+
readonly run: (ctx: SystemContext) => void;
|
|
55
|
+
/** Declared access, resolved to dense ComponentIds (pair ids included — ). Sorted, de-duped. */
|
|
56
|
+
readonly readIds: readonly ComponentId[];
|
|
57
|
+
readonly writeIds: readonly ComponentId[];
|
|
58
|
+
/** Packed access signatures for the O(words) disjointness test. length = accessStrideWords. */
|
|
59
|
+
readonly readWords: Uint32Array;
|
|
60
|
+
readonly writeWords: Uint32Array;
|
|
61
|
+
/** Explicit ordering edges, resolved to SystemIds. */
|
|
62
|
+
readonly before: readonly SystemId[];
|
|
63
|
+
readonly after: readonly SystemId[];
|
|
64
|
+
/** Reservation sizing for OP_CREATE mid-wave. */
|
|
65
|
+
readonly maxSpawnsPerWave: number;
|
|
66
|
+
/**
|
|
67
|
+
* Worker-eligibility: false if the system reads/writes any object<T> (restrictedToMainThread)
|
|
68
|
+
* component. Such a system is pinned to a main-thread batch; the
|
|
69
|
+
* object-field boundary is structural at schedule time, not a runtime throw.
|
|
70
|
+
*/
|
|
71
|
+
readonly workerEligible: boolean;
|
|
72
|
+
}
|
|
73
|
+
export declare const DEFAULT_MAX_SPAWNS_PER_WAVE = 64;
|
|
74
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/planner/types.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AACtF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAExC,oDAAoD;AACpD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;IACnB,2FAA2F;IAC3F,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;CAC/B;AAED;;;;GAIG;AACH,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAA;CAAE,GACvE;IAAE,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC,MAAM,CAAC,CAAA;CAAE,GAC9E;IAAE,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC,MAAM,CAAC,CAAA;CAAE,CAAA;AAEjF,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,uDAAuD;IACvD,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,YAAY,CAAC,MAAM,CAAC,EAAE,CAAA;IAC/C,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,YAAY,CAAC,MAAM,CAAC,EAAE,CAAA;IAChD,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,SAAS,EAAE,CAAA;IACtC,gDAAgD;IAChD,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,CAAA;IACrC,mCAAmC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;IACxC,8DAA8D;IAC9D,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;IAClC,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,IAAI,CAAA;IAC1C,qFAAqF;IACrF,QAAQ,CAAC,aAAa,CAAC,EAAE,IAAI,CAAA;CAC9B;AAED;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAA;IACvB,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,IAAI,CAAA;IAE1C,gGAAgG;IAChG,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAA;IACxC,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAA;IAEzC,+FAA+F;IAC/F,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAA;IAC/B,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAA;IAEhC,sDAAsD;IACtD,QAAQ,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,CAAA;IACpC,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAA;IAEnC,iDAAiD;IACjD,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;IAEjC;;;;OAIG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAA;CACjC;AAED,eAAO,MAAM,2BAA2B,KAAK,CAAA"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// System-definition public types and the internal
|
|
2
|
+
// lowered `SystemBox`. `defineSystem` lives in @ecsia/scheduler because the
|
|
3
|
+
// kernel runs single-threaded WITHOUT this package (`defineSystem` + `world.update`
|
|
4
|
+
// pull in the scheduler layer); a relation-free kernel never imports it.
|
|
5
|
+
export const DEFAULT_MAX_SPAWNS_PER_WAVE = 64;
|
|
6
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/planner/types.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,4EAA4E;AAC5E,oFAAoF;AACpF,yEAAyE;AA6EzE,MAAM,CAAC,MAAM,2BAA2B,GAAG,EAAE,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface WaitAsyncResult {
|
|
2
|
+
readonly async: boolean;
|
|
3
|
+
readonly value: 'ok' | 'not-equal' | 'timed-out' | Promise<'ok' | 'timed-out'>;
|
|
4
|
+
}
|
|
5
|
+
export declare function hasWaitAsync(): boolean;
|
|
6
|
+
/** Call Atomics.waitAsync. Caller MUST have probed `hasWaitAsync()` first. */
|
|
7
|
+
export declare function waitAsync(view: Int32Array, index: number, value: number): WaitAsyncResult;
|
|
8
|
+
//# sourceMappingURL=atomics-shim.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atomics-shim.d.ts","sourceRoot":"","sources":["../../src/workers/atomics-shim.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,GAAG,OAAO,CAAC,IAAI,GAAG,WAAW,CAAC,CAAA;CAC/E;AAMD,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED,8EAA8E;AAC9E,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,CAIzF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Localized shim for Atomics.waitAsync (lib ES2023 omits it; it is the ES2024 addition). The runtime
|
|
2
|
+
// (Node >= 20, capable browsers) provides it; we only need the type to call it on the tier-1 path.
|
|
3
|
+
// Probed at runtime before use (selectWaitTier), so on engines that lack it this code never runs.
|
|
4
|
+
export function hasWaitAsync() {
|
|
5
|
+
return typeof Atomics.waitAsync === 'function';
|
|
6
|
+
}
|
|
7
|
+
/** Call Atomics.waitAsync. Caller MUST have probed `hasWaitAsync()` first. */
|
|
8
|
+
export function waitAsync(view, index, value) {
|
|
9
|
+
const fn = Atomics.waitAsync;
|
|
10
|
+
if (fn === undefined)
|
|
11
|
+
throw new Error('Atomics.waitAsync unavailable (probe with hasWaitAsync first)');
|
|
12
|
+
return fn(view, index, value);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=atomics-shim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atomics-shim.js","sourceRoot":"","sources":["../../src/workers/atomics-shim.ts"],"names":[],"mappings":"AAAA,qGAAqG;AACrG,mGAAmG;AACnG,kGAAkG;AAWlG,MAAM,UAAU,YAAY;IAC1B,OAAO,OAAQ,OAAgC,CAAC,SAAS,KAAK,UAAU,CAAA;AAC1E,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,SAAS,CAAC,IAAgB,EAAE,KAAa,EAAE,KAAa;IACtE,MAAM,EAAE,GAAI,OAAgC,CAAC,SAAS,CAAA;IACtD,IAAI,EAAE,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAA;IACtG,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;AAC/B,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { WorkerPool } from './pool.js';
|
|
2
|
+
export type { PoolConfig, PoolSystem } from './pool.js';
|
|
3
|
+
export { makeWaveCounter, makeWaveSync, completeWave, setWaveError, waveErrored, workerHead } from './wave-sync.js';
|
|
4
|
+
export { makeReservationSab, fillReservation, takeReserved, consumedCount } from './reservation.js';
|
|
5
|
+
export type { WorkerReservationSab } from './reservation.js';
|
|
6
|
+
export { buildWorkerWorldView } from './world-view.js';
|
|
7
|
+
export type { WorkerWorldView } from './world-view.js';
|
|
8
|
+
export { matchComponentsOf } from './worker-system.js';
|
|
9
|
+
export type { WorkerSystemDef, WorkerSystemKernel, WorkerSystemBox } from './worker-system.js';
|
|
10
|
+
export type { WorkerBootstrap, ComponentManifestEntry, DispatchMessage } from './manifest.js';
|
|
11
|
+
export { hasWaitAsync, waitAsync } from './atomics-shim.js';
|
|
12
|
+
export type { WaitAsyncResult } from './atomics-shim.js';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/workers/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACtC,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AACnH,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AACnG,YAAY,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AACtD,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAC9F,YAAY,EAAE,eAAe,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC7F,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAC3D,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// @ecsia/scheduler/workers — the parallel execution layer: SAB allocation + one-time column/region
|
|
2
|
+
// transfer to a fixed worker pool, the wave dispatch loop, the three-tier Atomics wave-sync, the
|
|
3
|
+
// reservation Atomics.sub take path, and the deterministic command-buffer merge (serial-equivalence).
|
|
4
|
+
export { WorkerPool } from './pool.js';
|
|
5
|
+
export { makeWaveCounter, makeWaveSync, completeWave, setWaveError, waveErrored, workerHead } from './wave-sync.js';
|
|
6
|
+
export { makeReservationSab, fillReservation, takeReserved, consumedCount } from './reservation.js';
|
|
7
|
+
export { buildWorkerWorldView } from './world-view.js';
|
|
8
|
+
export { matchComponentsOf } from './worker-system.js';
|
|
9
|
+
export { hasWaitAsync, waitAsync } from './atomics-shim.js';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/workers/index.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,iGAAiG;AACjG,sGAAsG;AAEtG,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAEtC,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AACnH,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAEnG,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AAEtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAGtD,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA"}
|