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.

resource

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?)))

The 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:

units - The total number of units of the resource.
units-available - The number of units of the resource that are currently available (i.e. not allocated).
units-allocated - The number of units of the resource that are currently allocated.
satisfied - A set of resource allocations currently satisfied.
queue - A set of resource allocations yet to be satisfied.

make-resource

Function:
(make-resource units)
(make-unit)

Contract:

(case-> (-> (integer-in 1 +inf.0) resource?)
        (-> resource?))

This function returns a newly created resource instance with the specified number of units. If the number of units is not specified, 1 is used.

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.

resource-queue-variable-n

Function:
(resource-queue-variable-n resource)

Contract:

(-> resource? variable?)

This function returns the variable from the n field of the set in the queue field of resource.

resource-satisfied-variable-n

Function:
(resource-satisfied-variable-n resource)

Contract:

(-> resource? variable?)

This function returns the variable from the n field of the set in the satisfied field of resource.

7.2  Requesting and Relinquishing Resources

7.2.1  Requesting Resources

request

Macro:
(request resource [#:units units]
                  [#:priority priority]
                  [#:leave now 
                           (at time) 
                           (in delay) 
                           (when event) 
                           time])

Request units of resource. If the requested resources are not available, the request is queued with a priority of priority. The process requesting the resource(s) will delay until the resource(s) are available (and allocated to the process). It is an error to request more units of a resource than exist.

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.]

resource-request

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))

This is the functional equivalent to the request macro. This is used in legacy code to request resources.

7.2.2  Relinquishing Resources

relinquish

Macro:
(release resource [#:units units)]

Release units of resource. If the number of units to release is not specified, then all of units allocated to the process are released. It is an error to attempt to release more units than the process has allocated.

resource-relinquish

Function:
(resource-relinquish resource units)
(resource-relinquish resource)

Contract:

(case-> (-> resource?
            (integer-in 1 +inf.0)
            any)
        (-> resource?
            any))

This is the functional equivalent to the relinquish macro. This is used in legacy code to relinquish resources.

7.2.3  The with-resource Macro

with-resource

Macro:
(with-resource (resource units)
  body ...)

Since the sequence

  (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
>