ReviewOS

zig-utils/zig-js

Threads: synchronize async iterator helper records

#20
Closed chris opened this 11 days ago ·
11 days ago

Parent: #12, #1. Follow-up from #18.

Goal

Give AsyncIterator helper records (AsyncIterator.prototype.map/filter/take/drop/flatMap and AsyncIterator.from wrappers) the same no-GIL synchronization story as the sync lazy Iterator Helpers.

Current state

The sync helper paths now guard IterHelper.running / done state transitions with IterHelper.lock and avoid holding that lock across user callbacks or iterator next / return calls.

The async helper paths share the same IterHelper struct, but asyncIterHelperNextFn, asyncHelperProduce, and asyncIterHelperReturnFn still read/write helper fields directly:

  • done
  • started
  • counter
  • inner
  • running (currently unused by the async path)

That means same-helper cross-thread calls can race while one call is awaiting an underlying async iterator or callback.

Acceptance criteria

  • Decide/document whether AsyncIterator helpers are shared-realm callable from multiple JS threads or thread-affine.
  • If shared, use IterHelper.lock or an equivalent guard for async helper entry/exit and state publication.
  • Do not hold the helper lock across awaits, user callbacks, async iterator next, or async iterator return calls.
  • Define the concurrent .next() / .return() behavior while an async helper is already executing; prefer matching the sync helper running TypeError behavior if that fits the internal promise model.
  • Add focused no-GIL coverage for same-helper concurrent async .next() / .return() behavior.
  • Update docs/threads/bindings.md with the async helper ruling.
11 days ago

Implemented and validated.

Commit: cec5039 (fix(async-iterator): lock helper entry state)

What changed:

  • asyncIterHelperNextFn now uses IterHelper.lock to check running / done and publish running before entering async production.
  • asyncIterHelperReturnFn now rejects incompatible receivers, rejects same-helper concurrent entry, publishes done under the helper lock, and releases the lock before async iterator close calls.
  • Concurrent async helper .next() / .return() now reject their returned promises with TypeError, matching the sync helper policy.
  • Added a no-GIL regression where one thread blocks inside async helper .next() while the main thread verifies both concurrent .next() and .return() reject, then the original step completes normally.
  • Documented the async helper ruling in docs/threads/bindings.md.

Validation:

  • zig build test -Dtest-filter='parallel_js: AsyncIterator helper rejects concurrent entry while running' --summary none
  • zig build test -Dtest-filter='AsyncIterator' --summary none
  • git diff --check
11 days ago

Closing: async iterator helper entry/return state is synchronized in cec5039 with focused no-GIL coverage and docs updated.

Sign in to comment on this issue.