forked from simonmar/parconc-examples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
TBQueue.hs
40 lines (35 loc) · 1.24 KB
/
TBQueue.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
module TBQueue (TBQueue, newTBQueue, writeTBQueue, readTBQueue) where
import Control.Concurrent.STM
(STM, TVar, newTVar, readTVar, writeTVar, retry)
-- <<TBQueue
data TBQueue a = TBQueue (TVar Int) (TVar [a]) (TVar [a]) -- <1>
newTBQueue :: Int -> STM (TBQueue a)
newTBQueue size = do
read <- newTVar []
write <- newTVar []
cap <- newTVar size
return (TBQueue cap read write)
writeTBQueue :: TBQueue a -> a -> STM ()
writeTBQueue (TBQueue cap _read write) a = do
avail <- readTVar cap -- <2>
if avail == 0 -- <3>
then retry -- <4>
else writeTVar cap (avail - 1) -- <5>
listend <- readTVar write
writeTVar write (a:listend)
readTBQueue :: TBQueue a -> STM a
readTBQueue (TBQueue cap read write) = do
avail <- readTVar cap -- <6>
writeTVar cap (avail + 1)
xs <- readTVar read
case xs of
(x:xs') -> do writeTVar read xs'
return x
[] -> do ys <- readTVar write
case ys of
[] -> retry
_ -> do let (z:zs) = reverse ys
writeTVar write []
writeTVar read zs
return z
-- >>