Registry Internals
The registry layer is what assigns stable subcontext names to algorithms/states and makes value/type lookups predictable.
Core types:
NameSpaceRegistry: top-level registry (src/Registry/StructDefs.jl).RegistryTypeEntry{T}: one partition per entry type (src/Registry/StructDefs.jl).IdentifiableAlgo{F,Id,...,Key}: wrapped process entity with identity and assigned context key (src/Identifiable/StructDef.jl).
1. Type Partitions and Matching
Entries are grouped by assign_entrytype(obj) (src/Registry/Traits.jl).
- Default entry type: the object's type wrapper.
IdentifiableAlgooverrides this viaregistry_entrytype(::Type{<:IdentifiableAlgo{T}}) = T(src/Identifiable/IdentifiableAlgos.jl).
Within each RegistryTypeEntry, matches use match_by (src/Matching.jl, src/ProcessEntities/Matching.jl):
- Process entity instance (
Fib()): direct immutable instances match by value; other instances match by object identity. - Process entity type (
Fib): matches by type (match_by(::Type{<:ProcessEntity}) = T).
This is why instance-based and type-based registrations are distinct identities.
2. Key Assignment
add(reg, obj, multiplier) (src/Registry/Registries.jl, src/Registry/TypeEntries.jl) does:
- Find/create the correct
RegistryTypeEntry. - If no match exists, create a key with
Autokey(TypeName_index) and wrap asIdentifiableAlgo. - If a match exists, reuse the existing key and increase multiplier.
Key consequences:
- Same value entered repeatedly: same key reused.
- Same type entered repeatedly: same key reused for that type identity.
- Type-entered value vs value-entered value can still be different identities.
- This stays true across nested
CompositeAlgorithm/Routinetrees becausesetup_registryflattens all entities into one registry pass before context creation.
3. Unique and Distinguishability
Unique(f) builds an IdentifiableAlgo with a fresh UUID identity (src/Identifiable/StructDef.jl).
That gives a guaranteed distinct match identity even when the wrapped value is otherwise indistinguishable.
This is the mechanism used when you need multiple logically separate instances of the same algorithm in one composition.
4. Lookup Behavior
ProcessContext lookups by value/type eventually call registry getindex (src/Context/ProcessContexts.jl, src/Registry/Registries.jl).
The registry also supports direct symbol-key lookup:
reg[:Fib_1]returns the registeredIdentifiableAlgo
That is the same key space used by:
resolved[:Fib_1]on resolved loop algorithmsctx[:Fib_1]on process contexts
Important runtime detail in NameSpaceRegistry.getindex:
Type, direct immutable values, andAbstractIdentifiableAlgovalues use the static lookup path.- other values use the dynamic lookup table keyed by
match_by(obj).
So direct immutable instances can match equal values, while ordinary mutable instances match by object identity. Unique(...) gives an explicit fresh identity when the default rules are not what you want.
5. Multipliers
Each registry entry tracks a multiplier (RegistryTypeEntry.multipliers).
For loop algorithms this is derived from composition structure (intervals/repeats), and is used by utilities such as processsizehint!/num_calls (src/Tools.jl).
6. Order Guarantees
setup_registry adds:
ProcessStates first.- Then flattened algorithms.
(see src/LoopAlgorithms/Setup.jl)
That ordering controls init/cleanup traversal order through all_algos(registry).