Blob


1 ;; Exercise 3.42. Ben Bitdiddle suggests that it's a waste of time to create a new serialized procedure in response to every withdraw and deposit message. He says that make-account could be changed so that the calls to protected are done outside the dispatch procedure. That is, an account would return the same serialized procedure (which was created at the same time as the account) each time it is asked for a withdrawal procedure.
3 (define (make-account balance)
4 (define (withdraw amount)
5 (if (>= balance amount)
6 (begin (set! balance (- balance amount))
7 balance)
8 "Insufficient funds"))
9 (define (deposit amount)
10 (set! balance (+ balance amount))
11 balance)
12 (let ((protected (make-serializer)))
13 (let ((protected-withdraw (protected withdraw))
14 (protected-deposit (protected deposit)))
15 (define (dispatch m)
16 (cond ((eq? m 'withdraw) protected-withdraw)
17 ((eq? m 'deposit) protected-deposit)
18 ((eq? m 'balance) balance)
19 (else (error "Unknown request -- MAKE-ACCOUNT"
20 m))))
21 dispatch)))
23 ;; Is this a safe change to make? In particular, is there any difference in what concurrency is allowed by these two versions of make-account ?
25 ;; Yes, it's safe.
27 ;; At first I was concerned because I thought if you had a reference to the exact same procedure, you might be able to execute that same procedure again before another execution of that procedure terminated. The thing is that protected-withdraw and protected-deposit will return the exact same procedure whereas (protected withdraw) and (protected deposit) return new procedures each time. However, this does not matter if you check the implementation of the serializer. This is because only one mutex can be acquired, and it does not matter if the exact same procedure tries to grab the mutex -- only one procedure can run at any given time. Trying to run two instances of the exact same procedure will also fail.