Skip to content

Crew/Branch Content Ownership ​

How crew and branch content objects are owned and shared. Read this before touching how crew/branch objects are created, posted, executed, or cleared.

The object graph ​

A branch content element (BranchGoal, BranchAction, BranchExpectedParameterValue, …) is created once and then observed and mutated through several containers over its life:

  1. Cluster branch: BranchProbability : public CommunicationPlace : public BranchUnit inside BranchCluster::all_branch. The PE node's permanent record; read at the final savePENodeToFile.
  2. Command center: when a branch is taken, BranchProbability::sendBranchInfoToCommandCenter hands each element to CommandControlCenter::add*, which stores it in a CommandControlUnit member for execution scheduling.
  3. Communication place: when a command fires, the unit's member is moved into g_sim.Communication_place (a CommunicationPlace bulletin board) for crew perception.
  4. Crew views: memory.new_info (a CommunicationPlace) aliases CP elements during perception; the scan queue (KBScannedParameters) posts its own items into CP each panel scan.

The aliasing determines the outputs. Execution updates flow through the shared object (for example, timer fields set after publication), and PE files record the post-execution values. Replacing the sharing by deep copies changes the content of the PE files.

The ownership rule ​

Every container in the graph above holds std::shared_ptr<T>:

  • BranchUnit's 18 content vectors and CommunicationPlace's 3 extras
  • CommandControlUnit's 21 per-type members
  • KBScannedParameters' 4 scan lists

Posting an element to another container is a plain shared_ptr copy, never unique_ptr<T>(x.get()) and never shared_ptr<T>(x.get()) (a second control block is a double free). The CommandControlCenter::add* functions take const shared_ptr<T>&, so callers pass the pointer itself.

Containers that are sole owners stay unique_ptr: BranchCluster:: all_branch, the HW/SS staging wrappers (VHWReliabilityUnit etc.), OperatorAT/DM::ordered_* lists, BranchRecord::system_branch, and the *_branches definition records. They never exchange pointers with the shared graph; content crosses that boundary by deep copy only.

Deep-copy functions (copyBranchUnit, copyCommandControlUnit, …) remain deep: snapshots and clusters stay isolated by construction. Boost serializes the shared structure once per archive and restores true sharing on load. The checkpoint format that carries this layout is version 9, and the loader refuses files with a lower version (DETCheckpoint::version_supported()).

Why the ownership is shared ​

An element is reachable from several containers with different lifetimes. A command that is still pending when a sequence ends is dropped by CommandControlCenter::clearCommandControlCentePointer(), while the cluster branch that refers to the same element lives until the final savePENodeToFile(). With shared_ptr, clearing a container drops one reference and the element stays alive as long as any other container holds it, so the clear functions are plain clear() calls and no container needs to know which of the others still uses an element.

PU::serialize_object LZ4-compresses only streams of up to 4 MiB (structured crew and branch-record payloads). Larger streams, which are dominated by the RELAP5 restart image, ship raw behind a negative original-size header: compressing them would put the compressor on the dispatch path, and the encoding of the restart image belongs to the opt-in --compress-queue layer. Measure a new machine's economics with scripts/mpi_transport_probe.sh before tuning.

ADS-IDAC Engine Documentation