ReleaseMicrosoftMicrosoftpublished Apr 1, 2026seen Jun 26

microsoft/bocpy v0.3.0

microsoft/bocpy

Open original ↗

Captured source

source ↗
published Apr 1, 2026seen Jun 26captured 3whttp 200method plain

v0.3.0

Repository: microsoft/bocpy

Tag: v0.3.0

Published: 2026-04-01T22:42:20Z

Prerelease: no

Release notes: Improvements

  • Added CownCapsule.disown() — abandons a cown's value without

serializing it and resets ownership to NO_OWNER. Used during worker cleanup to safely discard orphan cowns before the owning interpreter is destroyed, preventing dangling Python object references.

  • Rewrote receive to use a two-phase spin-then-park strategy for

single-tag untimed receives. Phase 1 spins for BOC_SPIN_COUNT iterations; Phase 2 parks the thread on a per-queue condvar, eliminating busy-wait CPU burn. Timed receives and multi-tag receives use spin-then-backoff with exponential sleep (1 µs → 1 ms cap).

  • Added platform-abstracted condvar primitives (BOCParkMutex /

BOCParkCond) with implementations for Windows (SRWLOCK / CONDITION_VARIABLE), macOS (pthreads), and Linux (C11 threads).

  • Each BOCQueue now carries a waiters counter, park_mutex, and

park_cond. Producers signal parked receivers after enqueue; drain and set_tags broadcast to wake all parked threads.

  • Replaced the fixed thrd_sleep in send with a sched_yield /

SwitchToThread, reducing send-side latency.

  • Refactored the monolithic _core_receive into receive_single_tag

and receive_multi_tag, each with its own backoff/parking logic.

  • Moved the BOC_QUEUE_DISABLED check earlier in get_queue_for_tag

so callers skip disabled queues instead of returning NULL after tag resolution.

  • Added Windows-compatible atomic_load_explicit /

atomic_fetch_add_explicit / atomic_fetch_sub_explicit macros using InterlockedExchangeAdd64.

  • Declared Py_mod_gil = Py_MOD_GIL_NOT_USED in both _core and

_math C extensions so that importing bocpy on a free-threaded Python build (3.13t+) does not re-enable the GIL.

  • Replaced PyDict_GetItem (borrowed reference) with

PyDict_GetItemRef (strong reference) in BOCRecycleQueue_recycle on Python 3.13+, improving forward-compatibility with free-threaded builds.

Bug Fixes

  • Fixed a deadlock when the same cown is passed multiple times to @when

(e.g. @when(c, c)). Duplicate requests for the same cown caused the MCS-queue-based two-phase locking to spin-wait on itself. Requests are now deduplicated by target cown in Behavior.__init__, with compensating resolve_one calls to maintain the behavior count invariant.

Tests

  • TestLostWakeStress: single-producer random delays, bursty producer,

and repeated single-message wake to detect lost-wake races.

  • TestMultiTagBackoff: multi-tag receive correctness — second-tag hit,

delayed arrival, per-tag FIFO ordering, timeout, and interleaved producers.

  • TestTimeoutAccuracy: lower-bound / upper-bound wall-clock checks and

zero-timeout immediacy.

  • Added tests for duplicate cowns in @when: same cown twice, thrice,

non-adjacent duplicates, duplicates within a group, and mutation aliasing semantics.

CI

  • Added a free-threaded CI job that tests against Python 3.13t and

3.14t on Linux, with explicit assertions that the GIL remains disabled after import.

Full Changelog: https://github.com/microsoft/bocpy/compare/v0.2.2...v0.3.0