On this page
ReleaseManagedSpell๏
Use md.ReleaseManagedSpell from the public package namespace.
- class ReleaseManagedSpell(*args: object, **kwargs: object)[source]๏
The one way back for managed objects: a process singleton that routes an object to the pool it came from.
- Purpose:
Give an object leased from an Existence.managed_spell_quantity pool back to that pool - release(obj) - without a conduit, a spell id or a pool in hand. It keys every live pool by its managed class, so the common release is one dict get by type(obj) and the pool's put_back. A class managed by several pools (two binding names, two roots, two versions of one index) is resolved on a cold path: the active version wins, and otherwise spell_id= or conduit= picks the pool.
Responsibilities:
release(obj, *, spell_id=None, conduit=None): give one object back (the pool runs its resets, then the object is idle for the next lease).
managed(obj, ...): a ManagedSpellLease whose release() or with block gives it back once.
release_all(objects, ...): release many; failures are raised together after every attempt.
describe(cls): one snapshot per pool of a class - mode, count, idle and out objects, where it lives.
register(pool, ...) / unregister(pool): kept by the root stores as they take and give up pools, so the registry holds exactly the pools live stores hold.
Contract:
A process singleton with Aether's hosted-root shape (owner ruling 2026-10-15): Aether.__init__ builds it (ReleaseManagedSpell(aether=self), last, after Nexus), Aether.cleanup cleans it right after the frames, and ReleaseManagedSpell() returns that instance. A first construction without its host refuses.
Releasing never goes through Aether as a verb (owner ruling 2026-10-13) and never needs a conduit.
Identity is not tracked (owner, 2026-10-14): an object of a managed class is trusted to come from that class's pool; nothing records which objects are out.
The registry borrows the pools: it never cleans or disposes one. Each belongs to its root's store.
A class key is the exact class object: a subclass is a class of its own, and a redefined class (a new class object) is a new key.
Owned State:
_pools_by_class: class -> tuple of pools. The release fast path reads it without a lock.
_registrations: id(pool) -> (class, id of the root whose store holds the pool), for the cold paths.
_lock: a leaf lock held only to publish new maps.
Both maps are replaced whole (copy-on-write) and never mutated after they are published, so a lock-free reader always sees one complete map.
Threading:
release on a one-pool class with no filter takes no lock: one attribute read, one dict get, then the pool's own lock-free put-back.
register and unregister build new maps under _lock and publish _registrations then _pools_by_class. _lock is never held with another lock and runs no user code.
Singleton construction and reset take the class-level _singleton_lock; Aether.__init__ builds this object under Aether._lock, so the nesting is one-way Aether -> ReleaseManagedSpell.
- Performance:
Measured 2026-10-15 (CPython 3.14.7t, both GIL modes): a bound release adds about 50 ns over the pool's own put_back; the singleton call ReleaseManagedSpell() costs about 70 ns more, as Aether() does. A hot loop binds it once - release = ReleaseManagedSpell().release - and calls release(obj).
- Lifecycle / Cleanup:
cleanup() is idempotent: it publishes empty maps (tombstones, so lock-free readers racing it see an empty registry rather than missing fields), keeps _lock (a register or unregister racing it takes the lock and sees it cleaned) and resets the singleton bookkeeping. After cleanup release, managed, release_all, describe and register raise the cleaned RuntimeError; unregister does nothing (it is part of teardown). _reset_singleton_for_tests() cleans the live instance and clears the bookkeeping.
- Registration:
MELDER KERNEL - guarded. Created by Aether at boot; users call ReleaseManagedSpell() to reach it and never bind it as a spell.
- Subsystem Context:
The managed lifetime (EPIC-2026-10-14-managed_spell_quantity): each managed spell version has a ManagedSpellQuantity pool in its owning root's Creations; a meld or an injection leases from it; this registry gives objects back; root teardown disposes what the pool holds. An ownership transfer moves a pool between stores, and the stores re-register it under its new root.
- System Context:
Melder keeps the structure right - pools, this registry, the records that move with a transfer - and leaves the objects it hands out to the agents (src_architecture, "Runtime Model: Structure Is the Contract"). An object never released stays out and holds its place in a limited or queue pool until the root ends.
AGENT_ACCESS: public
- AGENT_PURPOSE:
access: public. Give managed objects back: ReleaseManagedSpell().release(obj) returns an object leased from a managed_spell_quantity pool (its resets run, it is reused by the next lease); managed(obj) gives a lease for a with block; release_all(objects); describe(cls) shows each pool's mode, count and idle objects. Pass spell_id= or conduit= only when one class is managed by several pools. In a hot loop bind it once: release = ReleaseManagedSpell().release.
- cleanup() None[source]๏
Retire the registry and reset the singleton.
Contract:
Idempotent and one-way.
Publishes empty maps as tombstones, so a lock-free reader racing this cleanup sees an empty registry, and the release fast path then misses and raises the cleaned error from the cold path.
Keeps _lock as a tombstone: a register or unregister racing this cleanup takes it and observes _cleaned instead of a missing field.
Never cleans a registered pool: pools belong to their stores, which unregistered them already when Aether tears its frames down first.
Resets _instance and _initialized unconditionally, as Aether does: a stale instance cannot unseat a live successor, because its cleanup returns at the cleaned check above.
- Threading:
Takes _lock to retire the maps, then _singleton_lock to reset the bookkeeping; never both at once.
- Returns:
None.
- register(pool: ManagedSpellQuantity, *, root_conduit_id: str) None[source]๏
Internal
Make a pool routable: called by a root store when it takes a pool (ensure at an owner stamp, a restore).
Contract:
Keys the pool by its managed class (pool.managed_class) and records the root whose store holds it.
Idempotent: the same pool, class and root register once. The same pool under a new root (a restore into another root) only moves its root; under a new class (a rebind that brought another class object) it moves to that class.
Publishes new maps; never mutates a published one.
- Parameters:
pool -- A live pool held by the calling store.
root_conduit_id -- Id of the root conduit whose store holds the pool now.
- Raises:
RuntimeError -- If the registry or the pool has been cleaned.
- Threading:
Takes the leaf _lock to read and publish; no user code runs under it.
- Returns:
None.
- unregister(pool: ManagedSpellQuantity) None[source]๏
Internal
Forget a pool: called by a store when it gives the pool up (extract, a restore replacing it, its cleanup).
Contract:
Idempotent: an unregistered pool, or a second call, does nothing.
Does nothing on a cleaned registry: unregistering is part of teardown, and a registry already gone has nothing to forget.
The pool's class stays routable while it has other pools; a class with none left leaves the registry.
- Parameters:
pool -- The pool the calling store gives up.
- Threading:
Takes the leaf _lock to read and publish; no user code runs under it.
- Returns:
None.
- release(obj: object, *, spell_id: str | None = None, conduit: Conduit | None = None) None[source]๏
Give one leased object back to its pool.
- Purpose:
The common hand-back. With one pool for the object's class and no filter it is one dict get and the pool's put_back; otherwise the cold resolver picks the pool.
Contract:
The pool runs its reset methods in order, then the object is idle for the next lease; an elastic pool above its baseline may trim its oldest idle objects (disposed outside every lock).
Several pools for the class: spell_id keeps the pool of that version, conduit the pools held by its root (a root or one of its lessers names that root); when more than one remains, the pools whose version is the one its index selects are preferred; exactly one must remain.
Trusted, never checked: the object is assumed to be one this pool leased.
- Parameters:
obj -- An object leased from a managed spell's pool.
spell_id -- Optional spell_id picking one pool.
conduit -- Optional root conduit, or a lesser of it, picking the pools that root holds.
- Raises:
ValueError -- The class is managed by no live pool, the filters match none, or several remain.
TypeError -- spell_id is not a str, or conduit is not a Conduit.
RuntimeError -- The registry or the given conduit was cleaned, or the pool was torn down with its root (the object is then the caller's to dispose).
Exception -- What a reset raised, after the pool destroyed the object.
ExceptionGroup -- A raising reset whose disposal failed too, or an elastic trim's disposal failures.
- Threading:
The fast path takes no lock. Safe from any thread.
- Returns:
None.
- managed(obj: ManagedObjectT, *, spell_id: str | None = None, conduit: Conduit | None = None) ManagedSpellLease[ManagedObjectT][source]๏
Return a lease that gives one leased object back once, by release() or at the end of a with block.
Contract:
The pool is resolved now, exactly as release resolves it; the lease then needs no lookup.
with ReleaseManagedSpell().managed(obj) as o: releases o when the block ends, whether or not it raised, and never suppresses the block's exception.
- Parameters:
obj -- An object leased from a managed spell's pool.
spell_id -- Optional spell_id picking one pool.
conduit -- Optional root conduit, or a lesser of it, picking the pools that root holds.
- Raises:
ValueError, TypeError, RuntimeError -- As release raises them while resolving the pool.
- Returns:
The lease over obj and its pool.
- Return type:
- release_all(objects: Iterable[object], *, spell_id: str | None = None, conduit: Conduit | None = None) None[source]๏
Give many leased objects back, attempting every one.
Contract:
Each object is released as release(obj, spell_id=..., conduit=...) would; a failure does not stop the rest.
Every failure is raised together afterwards, in object order, as one ExceptionGroup.
- Parameters:
objects -- The leased objects (any iterable, consumed once).
spell_id -- Optional spell_id picking one pool for every object.
conduit -- Optional root conduit, or a lesser of it, picking the pools that root holds.
- Raises:
RuntimeError -- If the registry has been cleaned (nothing is released).
ExceptionGroup -- "Errors occurred releasing <n> of <m> managed objects", after every object was attempted.
- Returns:
None.
- describe(cls: type) Tuple[Dict[str, Any], ...][source]๏
Return one snapshot per live pool of a managed class.
Contract:
Each entry is the pool's own describe() (mode, limit, timeout, count, idle and out counts, retention, spell identity, children recorded) plus holding_conduit_id (the root whose store holds the pool now) and active_version (whether its version is the one its index selects).
Entries follow registration order; a class with no pool answers ().
A read: it creates, registers and changes nothing.
- Parameters:
cls -- The managed class.
- Raises:
TypeError -- If cls is not a class.
RuntimeError -- If the registry has been cleaned, or a pool was torn down with its root while it was being described.
- Returns:
The snapshots.
- Return type:
Tuple[Dict[str, Any], ...]