Multi-core simulation: grain movement and heat across a worker pool (t88 phase 3)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-28 03:23:43 -04:00
co-authored by Claude Opus 5.5
parent 20963c776e
commit 7468d00efb
35 changed files with 578 additions and 113 deletions
+39
View File
@@ -0,0 +1,39 @@
// Browser transport only; the simulation owns the schedule and shared state.
let threadStarting = null;
async function startThreads() {
const count = Math.max(1, Math.min(16, Math.floor(SET.workerCap) || 16, (navigator.hardwareConcurrency || 3) - 2));
if (simPool && simPool.world === mat && simPool.workers.length === count) return;
if (threadStarting) await threadStarting;
if (simPool && simPool.world === mat && simPool.workers.length === count) return;
threadStarting = (async () => {
if (simPool) for (const worker of simPool.workers) worker.terminate();
simPool = null;
if (!(mat.buffer instanceof SharedArrayBuffer)) throw Error('Shared memory is unavailable');
const url = URL.createObjectURL(new Blob([SIM_WORKER_SOURCE, '\nonmessage=e=>threadMessage(e.data);'], {type:'text/javascript'}));
const pool = { world: mat, workers: [], slots: [] };
try {
const ready = [];
for (let k = 0; k < count; k++) {
const worker = new Worker(url), slot = threadSlot();
pool.workers.push(worker); pool.slots.push(slot);
ready.push(new Promise((resolve,reject) => {
const deadline = performance.now() + 10000;
worker.onerror = e => {
const error = Error(e.message || 'Simulation worker failed');
threadFailure(slot, error); reject(error);
};
const poll = () => {
if (Atomics.load(slot.control,0)) resolve();
else if (performance.now() > deadline) reject(Error('Simulation worker startup timed out'));
else setTimeout(poll, 1);
};
poll();
}));
worker.postMessage({world:threadWorld(),slot});
}
await Promise.all(ready); simPool = pool;
} catch (e) { for (const worker of pool.workers) worker.terminate(); throw e; }
finally { URL.revokeObjectURL(url); }
})();
try { await threadStarting; } finally { threadStarting = null; }
}