Quiz Study Guide — Chapter 6
This deck is a checklist, not a summary. Every slide is phrased as something you should be able to state or recognize without looking it up.
The one-sentence distinction
In the event view the system reacts to events. In the process view the movement of entities through their processes implies the events.
The process-view core
ProcessModel, Entity, KSLProcessseize, delay, release, useResourceWithQ and RequestQEntityGeneratorCoordination
HoldQueue, Signal, SuspensionBlockingQueue: send and waitForItemsBlockage and BlockingActivitywaitFor in its three overloadsYou should be able to:
Entity relates to QObjectseize() returns and why release() takes itKSLProcessBuilder suspending functions and what each doesBlockingQueueBlockage::Customer, return@process, qualified this| Class | Role |
|---|---|
ProcessModel |
Subclass of ModelElement containing the coroutine architecture; manages cleanup |
Entity |
Inner class of ProcessModel, subclassing QObject, so waiting statistics are automatic |
KSLProcess |
Interface wrapping the coroutine; exposes isCreated, isSuspended, isRunning, isCompleted, isTerminated, isActivated |
KSLProcessBuilder |
The receiver inside process { ... } exposing the suspending functions |
EntityGenerator |
Inner class of ProcessModel creating entities and activating their default process |
A KSLProcess is implemented as a specially constructed Kotlin coroutine, mapped onto a ProcessCoroutine inner class — not Java threads and not a ScheduledExecutorService.
Process state properties: isCreated, isSuspended, isRunning, isCompleted, isTerminated, isActivated, plus processElapseTime — completion time minus start time, valid only after completion.
Entity states in the EntityState hierarchy include CreatedState, Scheduled, Active, WaitingForResource, and InHoldQueue. There is no CompletedState — entities terminate via process states.
process { ... } returns a KSLProcess.seize() returns an Allocation — it records which resource and queue were involved, so release(allocation = a) deallocates the right resource and checks the right queue.seize() if a unit is immediately available.delay() is implemented by scheduling an event for the end of the delay; the coroutine resumes at that point when the event fires.| Function | Purpose |
|---|---|
seize |
Request resource units; suspend if unavailable; return an Allocation |
delay |
Schedule an event for the duration; suspend until it fires |
release |
Return units of a resource via the Allocation |
use |
Convenience: seize, then delay, then release in one call |
waitFor |
Suspend until a KSLProcess, Signal, or Blockage releases it |
ResourceWithQ is a resource with a built-in RequestQ that holds waiting seize requests. It automatically tabulates NumBusyUnits, InstantaneousUtil, ScheduledUtil, WIP, and SeizeCount.RequestQ is a Queue subclass for seize requests. Supply it via seize(resource, queue = requestQ) so the entity waits in that queue — useful when two activities share one resource but need separate lines.ResourceWithQCIfc is a controlled-access view: clients can read statistics and configure non-running-state properties, but cannot mutate runtime state.Allocation pairs an entity with a resource and a queue.::Customer is a function reference to the no-argument constructor of the Customer inner class.generate() calls activate(entity.defaultProcess!!), using a GeneratorActionIfc inherited from EventGenerator.isDefaultProcess = true on the process() builder, or by setting the entity’s defaultProcess property directly.IllegalStateException.process() given a name is added to the entity’s processes map, keyed by that name, where it can be retrieved later.activate(c.pharmacyProcess) schedules the start of the coroutine — typically at the current time with a default priority — so it begins after the current event finishes. It does not run the process synchronously.Trap
An entity experiences exactly one process at a time. Activating a second process for an entity already running one is an error.
| Construct | Description |
|---|---|
HoldQueue |
A Queue subclass; entities cannot self-remove — other code calls removeAndResume(entity) or removeAllAndResume(). Collects queueing statistics. |
Signal |
Built on HoldQueue; signal(range) notifies entities by rank and they self-remove |
BlockingQueue |
senderQ, receiver RequestQ, and channelQ; suspends senders and receivers |
Suspension |
Low-level suspendFor() / resume() pair; no queueing statistics |
Blockage |
Semaphore-like gate over suspending code: startBlockage(b) / clearBlockage(b) |
HoldQueue and Signal are built on Queue, so they automatically collect waiting statistics. Raw Suspension does not.HoldQueue or Signal, never Suspension.HoldQueue cannot remove itself — other code must call removeAndResume(entity) or removeAllAndResume().Signal is layered on a HoldQueue, and signaled entities do self-remove.SignalExample, signal(0..4) is a Kotlin range giving the ranks (positions 0 through 4) of the entities in the hold queue to notify.Three internal queues:
senderQ — entities blocked at send() because the channel is fullRequestQ — entities blocked at waitForItems()channelQ — the actual channel holding itemsDefault capacity is Int.MAX_VALUE, so senders effectively never block on a full channel unless a capacity is supplied. On a truly full channel, send() suspends the sender in senderQ.
Selection: the default rule fills the next request in the request queue. FirstFillableRequest is a RequestSelectorIfc that scans the waiting queue and returns the first request that canBeFilled, or null.
send(this@Shirt, completedShirtQ) — issued by the Shirt entity, not the Order.activate(shirt.shirtMaking) in a loop. Those activations are scheduled at the current simulation time, but because the current event is still executing they remain pending until subsequent events fire — this is the source of pseudo-parallelism.seize(myPackager, queue = myOrderQ) for paperwork and seize(myPackager) for final packaging: same resource, different waiting queues.startBlockage(b) and cleared with clearBlockage(b); entities calling waitFor(b) suspend while the section is started.BlockingActivity specializes Blockage to wrap a delay; use it with the perform(blockingActivity) suspending function so the blockage is always cleared.BlockingResourceUsage, BlockingResourcePoolUsage, and BlockingMovement wrap blockages around use(), pool use(), and move() so you need not manage start/clear by hand.return@process — a labeled return targeting the process builder; used to exit early, as for a “leaver” student in the STEM mixer.this (this@Order, this@Shirt, this@Customer) — disambiguates which enclosing entity instance is meant, since the builder lambda has its own implicit receiver, the KSLProcessBuilder.toBoolean() — an extension function in KSLRandom converting 1.0 to true and 0.0 to false, as in myDecideToWander.value.toBoolean().Entity subclass per type.Recommended layout of a ProcessModel subclass:
ProcessModelprocess() definitionsAt the end of a replication, ProcessModel terminates entities still suspended and ensures no entity terminates while still holding resource allocations.
Because both views describe the same underlying stochastic system, the process-view pharmacy model reproduces the Chapter 4 event-view results exactly, given the same streams and run parameters.
seize() returns an Allocation, and the entity does not suspend when a unit is immediately available.Blockage must be cleared, and only its instantiating entity may start or clear it.BlockingQueue means senders never block on a full channel — but a bounded one suspends the sender rather than throwing or discarding.HoldQueue collects statistics; raw Suspension does not.simulate is not one of the KSLProcessBuilder suspending functions.Without looking back, answer these:
seize() return, and why does release() take that rather than the resource?BlockingQueue and what suspends in each.Blockage?EntityGenerator is given an entity type with no default process?waitFor can be given?