Class LoadController
- All Implemented Interfaces:
ILoadController,Serializable
INodeDepot state for one entity.
Design — flat one-level COW with on-demand deep isolation
Every instance has two fields:
ownMap— this instance's private depot writes. Always aConcurrentHashMap. The assessor writes here viaputFlexLoadNodeDepot(java.lang.String, com.dna.jopt.member.unit.pnd.depot.node.INodeDepot).parentMap: a snapshot of the parent's complete depot map at the momentpartialCopy()was called. Non-null only in COW copies. Never modified after construction.
Performance
partialCopy() copies the map entries, not the depots: the
child's parentMap is a snapshot of the parent's entries and the
child gets a fresh empty ownMap. No depot copying happens at clone time.
Copying is deferred to getFlexLoadNodeDepot(java.lang.String): only the specific depot
that an operator actually touches is deep-copied at the moment it is first
accessed on the clone.
Correctness — why deep copy in lazy isolation
Lazy isolation calls INodeDepot.copy() (deep — ILoad.copy()
per item), not partialCopy() (shallow — shared ILoad
references). This is essential: FlexLoadOperator calls
setLoad() directly on an ILoad object that is already inside
the depot's item list. A shallow copy would leave that object shared between
the clone and the parent, so mutations on the clone would corrupt the
parent's depot state. A deep copy gives the clone fully independent
ILoad objects.
Thread safety
Both maps are ConcurrentHashMap instances. get and
put are safe under concurrent assessor threads. parentMap
is never modified after construction, so reads are always safe.
ownMap is iterated with a weakly-consistent iterator in
partialCopy() — never throws CME.
- See Also:
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptioncopy()voidflatten()Promotes this COW copy to a standalone instance by mergingparentMapintoownMapand clearing the parent reference.getFlexLoadNodeDepot(String nodeId) Returns the depot fornodeId.Returns a merged view of this instance's map and all ancestors.Creates a COW child.booleanputFlexLoadNodeDepot(String nodeId, INodeDepot depot) void
-
Constructor Details
-
LoadController
public LoadController()Creates a standalone instance with an empty depot map.
-
-
Method Details
-
getNodeDepotMap
Description copied from interface:ILoadControllerReturns a merged view of this instance's map and all ancestors.Not on the hot path — used by result-extraction code that needs a complete snapshot. For hot-path reads, use
ILoadController.getFlexLoadNodeDepot(java.lang.String)directly.- Specified by:
getNodeDepotMapin interfaceILoadController
-
setNodeDepotMap
- Specified by:
setNodeDepotMapin interfaceILoadController
-
putFlexLoadNodeDepot
- Specified by:
putFlexLoadNodeDepotin interfaceILoadController
-
getFlexLoadNodeDepot
Returns the depot fornodeId.Checks
ownMapfirst (O(1)). On miss, checksparentMapand lazily isolates the depot intoownMapvia a deep copy (INodeDepot.copy()) so that the clone owns fully independentILoadobjects. Subsequent accesses for the same node hitownMapdirectly (O(1)).- Specified by:
getFlexLoadNodeDepotin interfaceILoadController
-
partialCopy
Creates a COW child.The child's
parentMapis a snapshot of the entries this instance can see at this moment. The child gets a fresh emptyownMap. No depots are copied at this point: copying is deferred to the firstgetFlexLoadNodeDepot(java.lang.String)call that missesownMap.A standalone instance keeps writing to its
ownMapwhen it is assessed again, so its map is copied as well instead of being shared with the child. If this instance is itself a COW copy (parentMap != null), the complete visible state (parent + own entries, own wins) is merged into the snapshot so the child always sees the full picture.- Specified by:
partialCopyin interfaceILoadController
-
copy
- Specified by:
copyin interfaceILoadController
-
flatten
public void flatten()Promotes this COW copy to a standalone instance by mergingparentMapintoownMapand clearing the parent reference.Optional but beneficial: makes the next
partialCopy()O(1) (Case 1) instead of requiring a merge step (Case 2).
-