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.

define-process

Macro:
(define-process (name . arguments)
  body ...)

This macro defines a new process with the specified name. Syntacticly, the 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

process

Structure:
process

Contract:

(struct process
        ((process-def process-def?)
         (event event?)
         (state integer?)))

This structure defines a process. The 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.

process-name

Function:
(process-name process)

Contract:

(-> process? symbol?)

This function returns the name of the specified process.

process-time

Function:
(process-time process)

Contract:

(-> process? real?)

This function returns the next event time of the specified process. This is the value of the time field of the event field of the process. This is useful in advanced simulations using the interrupt and resume simulation control functions.

set-process-time!

Function:
(set-process-time! process time)

Contract:

(-> process? real? any)

This function sets the next event time of the specified process. It sets the value of the 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.

make-process

Function:
(make-process process-def arguments)

Contract:

(-> process-def? list? process?)

This function creates a new istance of the process whose definition is process-def. The process instance event will have its function field set to the body function for the process with the specified arguments. The process instance event is not added to any event list and remains in the 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
>