Chapter 3, Modularity, Objects, and State
Exercise 3.44
I think it won’t work but can work with a small fix.
The problem is mainly how to read this assumption of the problem - You should assume that the balance in from-account is at least amount.
I think this assumption is possible only when we are entering the procedure transfer
but how can we assume the same in multi threaded environment when withdraw
is called. Because the code of the transfer
method does not have anyway to determine that when it calls withdraw
the balance has not changed since the time we entered the transfer
procedure..
Since the situation in which it wont work is rare, lets first start with another part of the question assuming that this will work.
The problem asks an interesting question that what is the difference between this and the earlier exercise if this will work then previous exercise should also work as they look same on the outset both require withdrawing some amount from one acccount and depositing the withdrawn amount in other account.
The difference is from previous exercise is amount
which is withdrawn in constant here and does not depend on the current balance when we initiate the transfer.(Ofcourse withdrawn amount must be more then the balance but this is a precondition not dependency). So in this case amount
can be more then the withdraw- yes, even assuming the condition that amount initially is more then the balance when we entered the procedure - in multiple account case - we might run into this problem.
Consider a situation(somewhat similar as of previous exercise) that we are doing transfers as:
T1 - Transfer 10$ from account A1 to A2
T2 - Transfer 10$ from account A3 to A1
T3 - Transfer 10$ from account A1 to A4
Now lets execute them in parallel and consider that A1, A2, A3, A4 all have 10$ initial balance.
Now if they execute in parallel - there can be a situation when initially we start transfer - enter the procedure transfer - because amount
was sufficeint(as mentioned in the problem to assume that we enter this procedure assuming that amount is sufficient) BUT in the middle first T1 happens and then T3 starts executing and tries to withdraw
from A1 and withdraw procedure completes with return value “Insufficient Funds”.
The problem is transfer method does not check the return value and completes its business by calling the deposit
procedure.
After adding a check and reporting error, however, it should work except that still the program is not deterministic - if T1 -> T2 -> T3 executes then there wont be any problem but if T1 -> T3 -> T2 executes then program will report error.
Note that the fix is just a small check:
1
2
3
4
5
(define (transfer from-account to-account amount)
(let (wrs ((from-account 'withdraw')))
(if (eq? wrs "Insuffecient Funds")
(error "Can not withdraw!")
((to-account 'deposit) amount))))
Thus we have not used sophisticated method that Loius purposes but just a small fix.
Well, there can be another solution - to allow negative balances in the accounts :)