#lang racket (define (make-mutex) (let ((the-mutex (make-semaphore 1))) (define (dispatch m) (cond ((eq? m 'acquire) (semaphore-wait the-mutex)) ((eq? m 'release) (semaphore-post the-mutex)))) dispatch)) (define (make-serializer) (let ((mutex (make-mutex))) (lambda (p) (define (serialized-p . args) (mutex 'acquire) (let ((val (apply p args))) (mutex 'release) val)) serialized-p))) (define (make-numbered-accounts n) (let ((global-serializer (make-serializer))) (global-serializer (lambda (balance) (define (withdraw amount) (if (>= balance amount) (begin (set! balance (- balance amount)) balance) "Insufficient funds")) (define (deposit amount) (set! balance (+ balance amount)) balance) (let ((number (begin (set! n (+ n 1)) n)) (balance-serializer (make-serializer))) (lambda (m) (cond ((eq? m 'withdraw) withdraw) ((eq? m 'deposit) deposit) ((eq? m 'balance) balance) ((eq? m 'serializer) balance-serializer) ((eq? m 'number) number)))))))) (define account (make-numbered-accounts 0)) (define a1 (account 100)) (define a2 (account 50)) (println (a1 'number)) (println (a2 'number)) (define (exchange a1 a2) (let ((delta (- (a1 'balance) (a2 'balance)))) ((a1 'withdraw) delta) ((a2 'deposit) delta))) (define (serialized-exchange a1 a2) (let ((s1 (a1 'serializer)) (s2 (a2 'serializer))) (let ((s (if (< (a1 'number) (a2 'number)) (lambda (f) (s1 (s2 f))) (lambda (f) (s2 (s1 f)))))) ((s exchange) a1 a2)))) (serialized-exchange a1 a2) (println (a1 'balance)) (println (a2 'balance))