#lang racket ;;; Example 6aa - Simple Accepts and Calls with Returned Value ;;; ;;; This example uses sequential lock/unlock accepts to implement the lock. This ;;; works, but is very fragile. In particular, if the entry calls to lock or ;;; unlock are out of order or otherwise unmatched, the lock will not perform ;;; as expected. (require (planet williams/simulation/simulation)) ;;; process (lock) ;;; entry (lock i) -> string? ;;; i : exact-nonnegative-integer? ;;; entry (unlock) -> void? ;;; This process implements a lock with sequential lock/unlock accepts. The lock ;;; entry takes a single argument, which is the id for the p1 process using the ;;; lock, and returns a string with a message indicating that the lock has been ;;; acquired. The unlock entry unlocks the lock. There is no internal state. (define-process (lock) (let loop () (accept caller (lock i) (format "locked for p1(~a)" i)) (accept caller (unlock)) (loop))) ;;; process (p1 i a-lock) ;;; i : exact-nonnegative-integer? ;;; a-lock : process? ;;; This process uses the lock to protect its critical region, which just does a ;;; random wait in this case. It prints the message returned from the lock call. (define-process (p1 i a-lock) (printf "~a: process p1(~a) started.~n" (current-simulation-time) i) (let ((msg (call a-lock (lock i)))) (printf "~a msg = ~s~n" (current-simulation-time) msg)) (printf "~a: process p1(~a) acquired lock.~n" (current-simulation-time) i) (wait (random-flat 0.0 10.0)) (printf "~a: process p1(~a) releasing lock.~n" (current-simulation-time) i) (call a-lock (unlock))) ;;; (main n) -> void? ;;; n : exact-nonnegative-integer? ;;; Creates the lock process and schedules n p1 processes that use the lock. (define (main n) (with-new-simulation-environment (let ((a-lock (schedule #:now (lock)))) (for ((i (in-range n))) (schedule #:at (random-flat 0.0 10.0) (p1 i a-lock))) (start-simulation)))) ;;; Test with 10 p1 processes. (main 10)