Processes and Simulated Time
A process is an active entity in the simulated world. In cimba.sim, a
process is an ordinary Python function registered with @model.process.
Inside that function, sim.hold() and entity methods such as
env.queue.get() and env.resource.acquire() can pause the process and
let another scheduled activity run.
import cimba.random as random
@model.process
def doctor(env: Clinic):
while True:
env.waiting_room.get(1)
service_time = random.exponential(env.mean_service)
sim.hold(service_time)
env.served += 1
There is no yield in the process body. If the waiting room is empty,
env.waiting_room.get() blocks the doctor process until an arrival puts a
patient in the queue. When the process resumes, execution continues
immediately after the blocking call.
Simulated time, not wall-clock time
sim.hold(duration) advances the process in simulated time. It does not
sleep the operating-system thread for that many seconds.
started = sim.now()
sim.hold(15.0)
elapsed = sim.now() - started
The dispatcher always runs the next scheduled event in time order. A trial may simulate hours, days, or years while the real program takes far less wall-clock time.
Blocking is the modeling language
Most process interactions are expressed by blocking on a model entity:
sim.hold()waits for simulated time.env.<queue>.get()waits for enough content in asim.Queue.env.<resource>.acquire()waits for asim.Resource.env.<pool>.acquire()waits for capacity in asim.Pool.env.<condition>.wait_for()waits until asim.Conditionpredicate is true.
When the operation can complete, the process resumes. Blocking calls return a signal value, so a process can react to interruption, timeout, cancellation, or normal success when the model needs that detail.
Process copies
Use copies= when the model has several identical active entities:
@model.process(copies=3)
def clerk(env: Clinic, idx: int):
while True:
env.waiting_room.get(1)
sim.hold(random.exponential(env.mean_service))
env.served += 1
The second argument receives the copy index. Use it when each copy needs a
stable number for routing, logging, or separate state. If the copies are truly
interchangeable, a sim.Pool may be a better fit than multiple process
copies.
Process code should stay focused
Process bodies are compiled for the hot simulation loop. Keep them mostly to
numeric control flow, env fields, and sim calls. Do setup, plotting,
dataframe work, and rich Python object manipulation outside the trial run.
For a complete model that starts simple and then adds stopping, logging, resources, and richer behavior, see the tutorial.