Skip to content

Latest commit

 

History

History
91 lines (77 loc) · 5.81 KB

File metadata and controls

91 lines (77 loc) · 5.81 KB

Threads

zig-js supports two complementary thread models:

Model What shares What crosses Primary docs
Agent / worker isolation No JS heap state; each OS thread owns a Context, global object, jobs, allocator state, and exception state. Structured-clone bytes and retained SharedArrayBuffer storage. Agents, Workers
Shared-realm Thread One Context, global object, heap, shape tree, and object identity. Same-realm function arguments and return values. Thread API, Phase 6, GIL removal

The shared-realm model is now true-parallel by default:

const ctx = try js.Context.createWith(gpa, .{ .enable_threads = true });

That installs Thread, Lock, Condition, ThreadLocal, ConcurrentAccessError, property-mode Atomics.*, and proposal-aligned Atomics.Mutex / Atomics.Condition. Spawned Threads run JavaScript concurrently on real OS threads over the GC-managed, thread-safe heap.

The serialized fallback is still supported when deterministic GIL interleavings or legacy compatibility are useful:

const ctx = try js.Context.createWith(gpa, .{
    .enable_threads = true,
    .gil = true,
});

The C API exposes the same choice with ZJSGlobalContextCreateThreaded(gil). Non-threaded contexts remain single-threaded and keep the original affinity rules.

Shipping Surface

Area Status Verification
Refcounted SharedArrayBuffer storage Implemented in src/shared_buffer.zig and typed-array storage in src/value.zig. Unit tests, test262 SAB / Atomics shards, TSan gates.
WebAssembly shared memory and atomic execution Complete atomic opcode execution, SeqCst RMW/CAS/fence, wait32/wait64/notify, fixed historical Memory buffers, and targeted termination interruption. Terminal proposal-script/TSan/scaling evidence remains in issue #287. Pinned threads/atomic.wast 372/372, 1,069-test root, focused overlapping-access TSan witnesses.
$262.agent and typed-array Atomics.wait / notify / waitAsync Implemented in src/agent.zig with hooks in the interpreter and VM. Unit tests and real test262 agent cases.
Structured clone and ArrayBuffer transfer/detach Implemented in src/structured_clone.zig. Unit tests, workers, and agents.
Embedder Worker API Implemented in src/worker.zig with C-API hooks in src/c_api.zig. Worker unit tests, exact host-hook wake coverage, and C-API round trips.
Shared-realm Thread API Implemented in src/jsthread.zig, src/gil.zig, and src/context.zig; parallel by default, GIL opt-out available. PR-249 coverage: 248 promoted of 259 executable files (243 default plus 5 parallel_js-only); the inventory checksums all 339 files and distinguishes 5 optimizing-tier blockers from 6 terminal premises. Disposition probes, no-GIL TSan, and fuzzers guard the surface.
Concurrent GC / root safety GC-managed parallel contexts use thread-safe allocation, write barriers, per-structure locks, precise VM frame roots, and conservative native-stack rooting where applicable. Unit tests, parallel_gc soak, no-GIL corpus TSan, test262-parallel.

Core Rules

  • Context.createWith(.{ .enable_threads = false }) installs no Thread globals and keeps the original single-thread affinity rule.
  • Context.createWith(.{ .enable_threads = true }) runs shared-realm Threads in parallel by default and implies the GC-managed, thread-safe cell path.
  • Context.createWith(.{ .enable_threads = true, .gil = true }) keeps the same JavaScript API but serializes execution behind the context GIL.
  • Blocking APIs (join, Lock, Condition, typed-array Atomics wait, and property-mode Atomics wait) use their own synchronization paths in no-GIL mode and release the context GIL in serialized mode.
  • Object shapes, named properties, elements/collections, environments, promises, microtasks, inline caches, thread records, waiter queues, and shared-buffer storage each have explicit synchronization. New mutable shared state must follow that pattern.
  • JavaScript program races are distinct from engine-state races. See Memory Model for the public contract and the ThreadSanitizer suppression boundary.
  • Test-only knobs such as parallel_js and parallel_midscript_gc remain internal harness controls. They are not stable embedder APIs.
  • Process-global mutable state must be listed in bindings.md with a per-thread, locked, or refused ruling.

Reading Order