Processes
In a simulation model, a process represents an entity in the simulation that actively progresses through time.
In the PLT Scheme Simulation Collection, a process encapsulates an event that that executes the body of the process; provides state information for the process; and, most importantly, provides a handle that allows the process to interact with other simulation objects (e.g. resources or other processes).
6.1 Defining a Process
A process is defined using the define-process
macro.
Macro:
(define-process (name . arguments) body ...) |
|
define-process
macro is the same as define
for a function - indeed, an unnamed procedural object is created and associated with the process. However, the simulation collection maintains references to process object, thus allowing them to interact with each other.
The symbol name
is bound to the process definition for the process. This is used in creating a process instance.
The variable self is bound to the process instance during the execution of the process.
6.2 Creating and Accessing Processes
6.2.1 The process Structure
Structure:
process |
Contract: (struct process ((process-def process-def?) (event event?) (state integer?))) |
|
process-def
field points to a structure that contains information form the process definition needed internally by the simulation collection. The event
field contains the event object that represents the execution of the body of the process. The state
field contains the state of the process. Note that there are other fields used for continuous processes. These are described in Chapter 10, Continuous Simulation Models.There are a few short-cut functions that return information from the other structures pointed to by a process.
Function:
(process-name process) |
Contract: (-> process? symbol?) |
|
Function:
(process-time process) |
Contract: (-> process? real?) |
|
time
field of the event
field of the process. This is useful in advanced simulations using the interrupt
and resume
simulation control functions.
Function:
(set-process-time! process time) |
Contract: (-> process? real? any) |
|
time
field of the event
field of the process. This is useful in advanced simulations using the interrupt
and resume
simulation control functions.
6.2.2 Creating Processes
The normal way to create a process is using the schedule
macro as described in Section 4.1, Scheduling Events and Processes. This creates and schedules a process for execution.
There is also a primitive make-process
function that creates a process instance without scheduling its initial execution.
Function:
(make-process process-def arguments) |
Contract: (-> process-def? list? process?) |
|
PROCESS-CREATED
state.
6.2.3 Process States
Each process instance exists in a specific state at any specific point in its life. The current state of a process is available using the process-state
function. The following describes the possible process states:
- PROCESS-TERMINATED - the body of the process has finished execution.
- PROCESS-CREATED - the process has been created, but the body of the process has not begun executing. That is, the initial execution of the body of the process is scheduled, but has not occured.
- PROCESS-ACTIVE - the body of the process is executing.
- PROCESS-WAITING/WORKING - the process is currently in a
wait/work
. - PROCESS-WORKING-CONTINUOUSLY - the process is currently in a
work/continuously
. - PROCESS-DELAYED - the process is delayed waiting for a resource.
- PROCESS-INTERRUPTED - the process has been interrupted by another process via an
interrupt
call. - PROCESS-SUSPENDED - the process has suspended itself via a
suspend
call.
6.3 Example - Processes
This example is the same as the simulation model in Chapter 5. Indeed, the only syntactic difference is the use of define-process
instead of define
for the generator
and customer
processes.
; Example 1 - Processes (require (planet "simulation.ss" ("williams" "simulation.plt"))) (require (planet "random-distributions.ss" ("williams" "science.plt"))) (define-process (generator n) (do ((i 0 (+ i 1))) ((= i n) (void)) (wait (random-exponential 4.0)) (schedule now (customer i)))) (define-process (customer i) (printf "~a: customer ~a enters~n" (current-simulation-time) i) (work (random-flat 2.0 10.0)) (printf "~a: customer ~a leaves~n" (current-simulation-time) i)) (define (run-simulation n) (with-new-simulation-environment (schedule (at 0.0) (generator n)) (start-simulation)))
The output is identical to that of the simulation model in Chapter 5.
>(run-simulation 10) 0.6153910608822503: customer 0 enters 5.599485116393393: customer 1 enters 6.411843645405005: customer 2 enters 8.48917994426752: customer 0 leaves 10.275428842274628: customer 1 leaves 14.749397986170655: customer 2 leaves 23.525886616767437: customer 3 enters 27.18604340910279: customer 3 leaves 32.1644631797164: customer 4 enters 33.14558760001698: customer 5 enters 39.67682614849173: customer 4 leaves 40.486553934113665: customer 6 enters 41.168084930967424: customer 5 leaves 45.72670063299798: customer 6 leaves 46.747675912143016: customer 7 enters 49.212327970772435: customer 8 enters 50.556538752352886: customer 9 enters 51.46738784004611: customer 8 leaves 52.514846525674855: customer 7 leaves 56.11635302397275: customer 9 leaves >