-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMonitor.hs
64 lines (54 loc) · 1.75 KB
/
Monitor.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import Control.Concurrent.MVar
import Data.IORef
import Control.Concurrent
import Control.Monad
data Monitor = Monitor
{ monitorLock :: MVar ()
, monitorCond :: MVar [MVar ()]
}
-- | Repeatedly tests @b@ and runs @doit@ if false.
whileM :: IO Bool -> IO () -> IO ()
whileM cond body = undefined
-- | Create a new monitor object, which contains the lock as
-- well as the queue of condition variables threads are waiting on.
newMonitor :: IO Monitor
newMonitor = undefined
-- | Runs a computation within a monitor.
synchronized :: Monitor -> IO a -> IO a
synchronized m doit = undefined
-- | Inside a 'synchronized' block, releases the lock and waits
-- to be notified
wait :: Monitor -> IO ()
wait m = undefined
-- | Notifies the monitor that some conditions may have become true,
-- and wakes up one process.
notify :: Monitor -> IO ()
notify m = undefined
---------------------------------------------------------------------
-- Example code:
data Account = Account {
withdraw :: Int -> IO (),
deposit :: Int -> IO ()
}
newAccount :: IO Account
newAccount = do
m <- newMonitor
balance <- newIORef 0
return Account
{ withdraw = \n -> synchronized m $ do
putStrLn ("Withdrawing " ++ show n)
whileM (fmap (< n) $ readIORef balance) $ wait m
curr <- readIORef balance
writeIORef balance (curr - n)
, deposit = \n -> synchronized m $ do
putStrLn ("Depositing " ++ show n)
curr <- readIORef balance
writeIORef balance (curr + n)
notify m
}
makeAccountWithPendingWithdrawal = do
a <- newAccount
forkIO $ do
withdraw a 20
putStrLn "Withdrawal approved"
return a