#lang scribble/doc
@(require scribble/manual
scribblings/icons
(for-label scheme/base
plot/plot
"../simulation-with-graphics.ss"))
@title[#:tag "processes"]{Processes}
@local-table-of-contents[]
In a simulation model, a @deftech{process} represents an entity in the simulation that has state and actively progresses through (simulated) time.
In the PLT Scheme Simulation Collection, a process encapsulates an event 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 elements (e.g. resources or other processes).
@section{Defining a Process}
@defform[(defprocess (name . arguments)
body ...+)]{
Defines a new process with the specified @scheme[name]. Syntactically, the @scheme[define-process] macro is the same as @scheme[define] for a function---indeed, an unnamed procedural object us created and associated with the process. However, the simulation collection maintains references to process objects, thus allowing them to interact with each other and other simulation elements.
The symbol @scheme[name] is bound to the process definition for the process. This is used in creating process instances.
The variable @schemefont{self} is bound to the process instance during the execution of a process.}
@section{Creating and Accessing Processes}
@subsection{The @scheme[process] Structure}
@schemeblock[
(struct process (_process-def
_event
_state))
_process-def : process-def?
_event : event?
_state : integer?]
Represents a process instance.
@itemize{
@item{@schemefont{process-def}---points to a structure that contains information from the process definition needed internally by the simulation collection.}
@item{@schemefont{event}---contains the event object that represents the execution of the body of the process.}
@item{@schemefont{state}---maintains 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 processes.
@defproc[(process-name (process process?)) symbol?]{
Returns the name of the @scheme[process].}
@defproc[(process-time (process process?)) (>=/c 0.0)]{
Returns the time of the next event associated with @scheme[process]. This is the value of the @schemefont{time} fiels of the @schemefont{event} field of @scheme[process]. This is useful in simulations using the @scheme[interrupt] abd @scheme[resume] advanced simulation control functions.}
@defproc[(set-process-time! (process process?) (time (>=/c 0.0))) any]{
Sets the time of the next event associated with @scheme[process]. It sets the value of the @schemefont{time} fiels of the @schemefont{event} field of @scheme[process]. This is useful in simulations using the @scheme[interrupt] abd @scheme[resume] advanced simulation control functions.}
@subsection{Creating Processes}
The normal way to create a process is using the @scheme[schedule] macro as described in Section 4.1 Scheduling Events and Processes. This creates and schedules a process for execution.
@defproc[(make-process (process-def process-def?) (arguments (listof any?))) process?]{
Creates a new instance of the process whose definition is @scheme[process-def]. The process instance event will have it's @schemefont{function} field set to the body function for the process with the specified @scheme[arguments]. The process instance is not added to an event list and remains in the @schemefont{PROCESS-CREATED} state.}
@subsection{Process States}
Each process instance is in a specific state ar amy point in its life. The current state is available using the @scheme[process-state] function. The process states are:
@itemize{
@item{@schemefont{PROCESS-TERMINATED}---the body of the process has finished execution.}
@item{@schemefont{PROCESS-CREATED}---the process has been created, but the body of the process has not begun executing. If the process instance was created using the @scheme[schedule] macro, the initial execution of the body of the process is scheduled, but has not yet executed.}
@item{@schemefont{PROCESS-ACTIVE}---the body of the process is executing.}
@item{@schemefont{PROCESS-WAITING/WORKING}---the process is current in a @scheme[wait/work].}
@item{@schemefont{PROCESS-WORKING-CONTINUOUSLY}---the process is currently in a @scheme[work/continuously].}
@item{@schemefont{PROCESS-DELAYED}---the process is delayed waiting for a resource.}
@item{@schemefont{PROCESS-INTERRUPTED}---the process has been interrupted by another process via an @scheme[interrupt] call.}
@item{@schemefont{PROCESS-SUSPENDED}---the process has suspended itself via a @scheme[suspend] call.}
}
@section{Example---Processes}
This example is the same as the simulation model in Chapter 5. Indeed, the only syntactic difference is the use of @scheme[define-process] instead of @scheme[define] for the @schemefont{generator} and @schemefont{customer} processes.
@schememod[
scheme/base
(code:comment "Example 1 - Processes")
(require (planet williams/simulation/simulation))
(require (planet williams/science/random-distributions))
(define-process (generator n)
(for ((i (in-range n)))
(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)))
(run-simulation 10)
]
Produces the following output.
@verbatim{
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
}
A few things to note at this point are:
@itemize{
@item{The output of this example is identical to that of the example in Section 5.3 Example---Functions as Events.}
@item{For many simple processes, an event may be used instead. Events are lighter-weight than processes. For example, in subsequent simulation models we will use an event for the @schemefont{generator} function since it does not require any interaction with other processes---other than scheduling the @schemefont{customer} processes.}
}