class ChannelRegistryRef-counted, thread-aware projection registry.
Owns the spec.key → (store, runtime) mapping for one
StreamController. Lifecycle:
acquire(spec) → +1 ref, returns { store, release }. The
first acquire opens the projection's runtime; subsequent
acquires for the same key share both the store and the
runtime.release() → -1 ref. When the last consumer releases,
the entry is removed and its runtime disposed.bind(thread) → swap or detach the underlying thread; every
live entry's runtime is recreated against the new thread,
keeping the same store identity.dispose() → tear everything down (idempotent). Safe to
call multiple times.The registry is intentionally not generic over a state shape —
different consumers can hold projections producing different
snapshot types, so the registry keys everything as unknown and
lets acquire reapply the caller's T at the boundary.