Model Execution in ERS: Threading, SubModels, and Safety
In ERS, simulation execution is highly parallel, but also strictly controlled. To ensure both scalability and safety, ERS adopts a model where:
- Each Simulator is processed by only one thread at a time.
- All simulation data is encapsulated in a SubModel.
- The EventMechanism ensures safety, threads enter and exit SubModels.
- All runtime state is resolved through thread-local context.
This approach eliminates race conditions and avoids the need for fine-grained locks while modeling.
Why Entering & Exiting SubModels matters
A SubModel contains the data and logic for a single Simulator. It includes:
- The entities and components in that part of the simulation.
- Scheduled events (local and sync).
- The Simulator's internal simulation time.
Before a thread can safely operate on a SubModel, it must enter it explicitly:
NOTE: This is handled automatically during execution of the model by the EventMechanism, see diagram below
EnterSubModel();
// ... access submodel data, entities, components, schedule events ...
ExitSubModel();
This ensures that:
- Only one thread touches that SubModel's data at a time.
- The thread-local pointer is updated so runtime queries (like getting the current simulator ID, or sync-event context) resolve correctly.
- The SubModel becomes the active simulation context, ensuring correct behavior for all local logic.
- User code doesn't need to become complex to retrieve & update submodel data.
Without this entry/exit mechanism, it would be possible for threads to operate on the wrong data or interfere with each other — especially during nested callbacks or sync-events.
Thread-Local Architecture: No Locks Needed
ERS uses thread-local state to store context about the current SubModel and the currently active SyncEvent (if any).
This design has major advantages:
- All core functions like GetCurrentSimulatorID() or IsInsideSyncEvent() resolve via thread_local variables.
- Sync-events (with SenderSide and TargetSide) can be nested without confusion.
- No synchronization primitives (mutexes, atomics) are needed for SubModel access, as threads are isolated by design.