Overview
The Thread Synchronization Simulator uses a modular UI architecture where each synchronization scenario has its own dedicated UI module. All UI modules follow a consistent pattern for initialization, state management, and rendering.UI Module Structure
The UI system is organized into specialized modules, each handling a different synchronization primitive:- UI (
ui.js) - Mutex-based bank scenario - SemaphoreUI (
semaphoreUI.js) - Semaphore-based printer scenario - ConditionUI (
conditionUI.js) - Condition variables for restaurant scenario - BarrierUI (
barrierUI.js) - Barrier synchronization for race scenario - MonitorUI (
monitorUI.js) - Monitor pattern for library scenario - JoinUI (
joinUI.js) - Join/await for house construction scenario - PetersonUI (
petersonUI.js) - Peterson’s algorithm for robot station
Common Initialization Pattern
All UI modules follow theinit() pattern, which establishes the connection between the UI and the simulation engine:
ui.js
Key Components
- Engine Reference - The
engineparameter connects the UI to the simulation engine - Timeline - Each module creates its own
Timelineinstance for event logging - Context - Scenario-specific state (mutex, semaphore, etc.)
- Event Handlers - Connect DOM elements to simulation controls
UI Module Properties
Every UI module maintains these properties:Core Methods
Each UI module implements these standard methods:init(engine)
Initializes the UI module with a reference to the simulation engine.
Parameters:
engine- TheEngineinstance that executes simulation steps
semaphoreUI.js
runTick(engine, context, timeline)
Executes a single simulation step and updates the UI.
ui.js
startAuto(engine, context, timeline)
Starts automatic execution at 1-second intervals.
ui.js
stopAuto()
Stops automatic execution and resets the UI.
ui.js
update(engine, context)
Synchronizes the visual state with the simulation state. Each module implements this differently based on its scenario.
ui.js
Connecting UI to Engine
The UI modules connect to the simulation engine through a well-defined interface:Engine Integration
Engine Methods Used by UI
engine.step(context)- Executes one simulation tick, returns event logsengine.threads- Array of all threads in the simulationengine.tick- Current simulation tick counter
Scenario Context
Each scenario creates a context object that contains:bankScenario.js
engine.step() on each tick.
Scenario Generation Pattern
UI modules typically follow this pattern for generating scenarios:semaphoreUI.js
UI State Management
The UI modules manage state through:- Simulation State - Stored in
engine.threadsandcontext - UI State - Stored in module properties (
autoInterval,simulationFinished) - DOM State - Reflected in the rendered HTML elements
update() method ensures these states stay synchronized.
Render Functions
UI modules delegate rendering to specialized renderer functions:renderClients()- Renders thread cards with state visualization (source/js/ui/renderer.js:4)renderSemaphoreView()- Renders printer and job state (source/js/ui/semaphoreRenderer.js:5)renderConditionView()- Renders restaurant with chef and customers (source/js/ui/conditionRenderer.js:5)renderBarrierView()- Renders race checkpoint state (source/js/ui/barrierRenderer.js:5)renderMonitorView()- Renders library with readers and writerrenderJoinView()- Renders house construction stagesrenderPetersonView()- Renders robot station state
Example: Complete UI Flow
Here’s how the UI system works from start to finish:Best Practices
- Always stop auto-execution before generating a new scenario
- Clear the timeline when starting a new scenario
- Check for null context before running ticks
- Use
simulationFinishedflag to prevent duplicate completion messages - Delegate rendering to specialized renderer functions
- Follow the init() pattern for consistency across modules
Next Steps
- Renderer API - Learn about rendering thread states
- Timeline API - Understand event logging
- Engine API - Deep dive into the simulation engine