Skip to content

Commit 92af455

Browse files
authored
Merge pull request #9 from mitchellwrosen/master
Add lengthTBQueue, fix bug in flushTBQueue (fixes #8)
2 parents 33a36c3 + 4f63bbc commit 92af455

File tree

1 file changed

+32
-20
lines changed

1 file changed

+32
-20
lines changed

Control/Concurrent/STM/TBQueue.hs

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ module Control.Concurrent.STM.TBQueue (
3939
tryPeekTBQueue,
4040
writeTBQueue,
4141
unGetTBQueue,
42+
lengthTBQueue,
4243
isEmptyTBQueue,
4344
isFullTBQueue,
4445
) where
@@ -52,14 +53,15 @@ import GHC.Conc
5253
--
5354
-- @since 2.4
5455
data TBQueue a
55-
= TBQueue _UPK_(TVar Int) -- CR: read capacity
56-
_UPK_(TVar [a]) -- R: elements waiting to be read
57-
_UPK_(TVar Int) -- CW: write capacity
58-
_UPK_(TVar [a]) -- W: elements written (head is most recent)
56+
= TBQueue _UPK_(TVar Int) -- CR: read capacity
57+
_UPK_(TVar [a]) -- R: elements waiting to be read
58+
_UPK_(TVar Int) -- CW: write capacity
59+
_UPK_(TVar [a]) -- W: elements written (head is most recent)
60+
_UPK_(Int) -- CAP: initial capacity
5961
deriving Typeable
6062

6163
instance Eq (TBQueue a) where
62-
TBQueue a _ _ _ == TBQueue b _ _ _ = a == b
64+
TBQueue a _ _ _ _ == TBQueue b _ _ _ _ = a == b
6365

6466
-- Total channel capacity remaining is CR + CW. Reads only need to
6567
-- access CR, writes usually need to access only CW but sometimes need
@@ -83,7 +85,7 @@ newTBQueue size = do
8385
write <- newTVar []
8486
rsize <- newTVar 0
8587
wsize <- newTVar size
86-
return (TBQueue rsize read wsize write)
88+
return (TBQueue rsize read wsize write size)
8789

8890
-- |@IO@ version of 'newTBQueue'. This is useful for creating top-level
8991
-- 'TBQueue's using 'System.IO.Unsafe.unsafePerformIO', because using
@@ -95,11 +97,11 @@ newTBQueueIO size = do
9597
write <- newTVarIO []
9698
rsize <- newTVarIO 0
9799
wsize <- newTVarIO size
98-
return (TBQueue rsize read wsize write)
100+
return (TBQueue rsize read wsize write size)
99101

100102
-- |Write a value to a 'TBQueue'; blocks if the queue is full.
101103
writeTBQueue :: TBQueue a -> a -> STM ()
102-
writeTBQueue (TBQueue rsize _read wsize write) a = do
104+
writeTBQueue (TBQueue rsize _read wsize write _size) a = do
103105
w <- readTVar wsize
104106
if (w /= 0)
105107
then do writeTVar wsize $! w - 1
@@ -114,7 +116,7 @@ writeTBQueue (TBQueue rsize _read wsize write) a = do
114116

115117
-- |Read the next value from the 'TBQueue'.
116118
readTBQueue :: TBQueue a -> STM a
117-
readTBQueue (TBQueue rsize read _wsize write) = do
119+
readTBQueue (TBQueue rsize read _wsize write _size) = do
118120
xs <- readTVar read
119121
r <- readTVar rsize
120122
writeTVar rsize $! r + 1
@@ -143,16 +145,17 @@ tryReadTBQueue c = fmap Just (readTBQueue c) `orElse` return Nothing
143145
--
144146
-- @since 2.4.5
145147
flushTBQueue :: TBQueue a -> STM [a]
146-
flushTBQueue (TBQueue rsize read wsize write) = do
148+
flushTBQueue (TBQueue rsize read wsize write size) = do
147149
xs <- readTVar read
148150
ys <- readTVar write
149-
r <- readTVar rsize
150-
w <- readTVar wsize
151-
writeTVar read []
152-
writeTVar write []
153-
writeTVar rsize 0
154-
writeTVar wsize (r + w)
155-
return (xs ++ reverse ys)
151+
if null xs && null ys
152+
then return []
153+
else do
154+
writeTVar read []
155+
writeTVar write []
156+
writeTVar rsize 0
157+
writeTVar wsize size
158+
return (xs ++ reverse ys)
156159

157160
-- | Get the next value from the @TBQueue@ without removing it,
158161
-- retrying if the channel is empty.
@@ -176,7 +179,7 @@ tryPeekTBQueue c = do
176179
-- |Put a data item back onto a channel, where it will be the next item read.
177180
-- Blocks if the queue is full.
178181
unGetTBQueue :: TBQueue a -> a -> STM ()
179-
unGetTBQueue (TBQueue rsize read wsize _write) a = do
182+
unGetTBQueue (TBQueue rsize read wsize _write _size) a = do
180183
r <- readTVar rsize
181184
if (r > 0)
182185
then do writeTVar rsize $! r - 1
@@ -188,9 +191,18 @@ unGetTBQueue (TBQueue rsize read wsize _write) a = do
188191
xs <- readTVar read
189192
writeTVar read (a:xs)
190193

194+
-- |Return the length of a 'TBQueue'.
195+
--
196+
-- @Since FIXME
197+
lengthTBQueue :: TBQueue a -> STM Int
198+
lengthTBQueue (TBQueue rsize _read wsize _write size) = do
199+
r <- readTVar rsize
200+
w <- readTVar wsize
201+
return $! size - r - w
202+
191203
-- |Returns 'True' if the supplied 'TBQueue' is empty.
192204
isEmptyTBQueue :: TBQueue a -> STM Bool
193-
isEmptyTBQueue (TBQueue _rsize read _wsize write) = do
205+
isEmptyTBQueue (TBQueue _rsize read _wsize write _size) = do
194206
xs <- readTVar read
195207
case xs of
196208
(_:_) -> return False
@@ -203,7 +215,7 @@ isEmptyTBQueue (TBQueue _rsize read _wsize write) = do
203215
--
204216
-- @since 2.4.3
205217
isFullTBQueue :: TBQueue a -> STM Bool
206-
isFullTBQueue (TBQueue rsize _read wsize _write) = do
218+
isFullTBQueue (TBQueue rsize _read wsize _write _size) = do
207219
w <- readTVar wsize
208220
if (w > 0)
209221
then return False

0 commit comments

Comments
 (0)