summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Presence/LockedChan.hs72
1 files changed, 72 insertions, 0 deletions
diff --git a/Presence/LockedChan.hs b/Presence/LockedChan.hs
new file mode 100644
index 00000000..e7e951bb
--- /dev/null
+++ b/Presence/LockedChan.hs
@@ -0,0 +1,72 @@
1{-# LANGUAGE CPP #-}
2module LockedChan
3 ( LockedChan
4 , cloneLChan
5 , newLockedChan
6 , peekLChan
7 , unlockChan
8 , writeLChan )
9 where
10
11
12import Control.Monad.STM
13import Control.Concurrent.STM
14
15data LockedChan a = LockedChan
16 { lock :: TVar Bool
17 , chan :: TChan a
18 }
19
20unlockChan :: LockedChan a -> IO (TChan a)
21unlockChan c = do
22 waslocked <- atomically $ swapTVar (lock c) False
23 if waslocked
24 then return (chan c)
25 else error "Attempt to read unlocked channel"
26
27writeLChan :: LockedChan a -> a -> STM ()
28writeLChan c a = writeTChan (chan c) a
29
30peekLChan :: LockedChan a -> STM a
31peekLChan c = peekTChan (chan c)
32
33newLockedChan :: STM (LockedChan a)
34newLockedChan = do
35 lock <- newTVar True
36 chan <- newTChan
37 return $ LockedChan lock chan
38
39cloneLChan :: LockedChan a -> IO (LockedChan a)
40cloneLChan c = do
41 mchan <- atomically $ do
42 locked <- readTVar (lock c)
43 if locked
44 then fmap Just $ do
45 c2 <- cloneTChan (chan c)
46 l2 <- newTVar True
47 return $ LockedChan l2 c2
48 else return Nothing
49 return $ maybe (error "Attempt to clone unlocked channel")
50 id
51 mchan
52
53#if MIN_VERSION_stm(2,4,0)
54#else
55-- |Clone a 'TChan': similar to dupTChan, but the cloned channel starts with the
56-- same content available as the original channel.
57--
58-- Terrible inefficient implementation provided to build against older libraries.
59cloneTChan :: TChan a -> STM (TChan a)
60cloneTChan chan = do
61 contents <- chanContents' chan
62 chan2 <- dupTChan chan
63 mapM_ (writeTChan chan) contents
64 return chan2
65 where
66 chanContents' chan = do
67 b <- isEmptyTChan chan
68 if b then return [] else do
69 x <- readTChan chan
70 xs <- chanContents' chan
71 return (x:xs)
72#endif