Resources
In a simulation model, a resource represents an entity (or entities) that is/are shared among processes. Each resource has a quantity associates with it representing the number of those (indistinquishable) resources available.
7.1 The resource Structure
The resource structure represents a resource in a simulation model.
Structure:
resource |
Contract: (struct resource ((units (integer-in 1 +inf.0)) (units-available natural-number/c) (units-allocated natural-number/c) (satisfied set?) (queue set?))) |
|
resource
structure represents a resource, possibly with multiple allocatable units, in a resource model. When there are insufficient resources to fulfill a resource request, the request is queued until the rosource(s) are available. The queued request may include a priority and the process may reneg on a request based on time or the occurance of a specific event.The fields in the resource structure are:
Function:
(make-resource units) (make-unit) |
Contract: (case-> (-> (integer-in 1 +inf.0) resource?) (-> resource?)) |
|
7.1.1 Shortcuts to Resource Set Veriables
The resource
structure includes two sets to implement the queues of satisfied allocations (the satisfied
field) and the waiting allocations (the queue
field). The following functions provide access to the n
field of the respective sets to facilitate data collection.
Function:
(resource-queue-variable-n resource) |
Contract: (-> resource? variable?) |
|
n
field of the set in the queue
field of resource.
Function:
(resource-satisfied-variable-n resource) |
Contract: (-> resource? variable?) |
|
n
field of the set in the satisfied
field of resource.
7.2 Requesting and Relinquishing Resources
7.2.1 Requesting Resources
Macro:
(request resource [#:units units] [#:priority priority] [#:leave now (at time) (in delay) (when event) time]) |
|
The process may reneg on the request using the #:leave
keyword. The options for the #:leave
clause are the same as for the schedule
macro. [Note that specifying #:leave (in 0.0)
will reneg at the current time, but will allow all now
events to be executed, which may relinquish the resource(s) required. This is not the same as specifying #:leave now
and can be safer than checking the units-available
field.]
Function:
(resource-request resource units priority reneg) (resource-request resource units priority) (resource-request resource units) (resource-request resource) |
Contract: (case-> (-> resource? (integer-in 1 +inf.0) real? (union/c event? real?) any) (-> resource? (integer-in 1 +inf.0) real? any) (-> resource? (integer-in 1 +inf.0) any) (-> resource? any)) |
|
request
macro. This is used in legacy code to request resources.
7.2.2 Relinquishing Resources
Macro:
(release resource [#:units units)] |
|
Function:
(resource-relinquish resource units) (resource-relinquish resource) |
Contract: (case-> (-> resource? (integer-in 1 +inf.0) any) (-> resource? any)) |
|
relinquish
macro. This is used in legacy code to relinquish resources.
7.2.3 The with-resource Macro
Macro:
(with-resource (resource units) body ...) |
|
(resource-request resource units) ... (resource-relinquish)
is by far the most frequent use of resource-request
and resource-release
, the with-resource
is provided to simplify these calls. The body expressions are evaluated with the requested resource(s) allocated.
7.3 Example - Resources
This example extends the simple system of Chapters 5 and 6 by adding attendants to the system. Before leaving the system, each customer must interact with an attendent. The two attendants are modeled using a single resource with two units. This means there is a single queue for the two attendants. Again the output is a simple trace of customer arrivals, attendant acquisitions, and departures.
; Example 2 - Resources (require (planet "simulation.ss" ("williams" "simulation.plt"))) (require (planet "random-distributions.ss" ("williams" "science.plt"))) (define n-attendants 2) (define attendant #f) (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) (request attendant) (printf "~a: customer ~a gets an attendant~n" (current-simulation-time) i) (work (random-flat 2.0 10.0)) (relinquish attendant) (printf "~a: customer ~a leaves~n" (current-simulation-time) i)) (define (run-simulation n) (with-new-simulation-environment (set! attendant (make-resource n-attendants)) (schedule (at 0.0) (generator n)) (start-simulation)))
The simulation model is executed by calling (run-simulation n)
, where n is the number of customer to simulate through the system. For example, (run-simulation 10)
produces the following output:
>(run-simulation 10) 0.6153910608822503: customer 0 enters 0.6153910608822503: customer 0 gets an attendant 5.599485116393393: customer 1 enters 5.599485116393393: customer 1 gets an attendant 6.411843645405005: customer 2 enters 8.48917994426752: customer 0 leaves 8.48917994426752: customer 2 gets an attendant 10.275428842274628: customer 1 leaves 16.82673428503317: customer 2 leaves 23.525886616767437: customer 3 enters 23.525886616767437: customer 3 gets an attendant 27.18604340910279: customer 3 leaves 32.1644631797164: customer 4 enters 32.1644631797164: customer 4 gets an attendant 33.14558760001698: customer 5 enters 33.14558760001698: customer 5 gets an attendant 39.67682614849173: customer 4 leaves 40.486553934113665: customer 6 enters 40.486553934113665: customer 6 gets an attendant 41.168084930967424: customer 5 leaves 45.72670063299798: customer 6 leaves 46.747675912143016: customer 7 enters 46.747675912143016: customer 7 gets an attendant 49.212327970772435: customer 8 enters 49.212327970772435: customer 8 gets an attendant 50.556538752352886: customer 9 enters 51.46738784004611: customer 8 leaves 51.46738784004611: customer 9 gets an attendant 52.514846525674855: customer 7 leaves 57.02720211166597: customer 9 leaves >