@@ -39,6 +39,7 @@ module Control.Concurrent.STM.TBQueue (
39
39
tryPeekTBQueue ,
40
40
writeTBQueue ,
41
41
unGetTBQueue ,
42
+ lengthTBQueue ,
42
43
isEmptyTBQueue ,
43
44
isFullTBQueue ,
44
45
) where
@@ -52,14 +53,15 @@ import GHC.Conc
52
53
--
53
54
-- @since 2.4
54
55
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
59
61
deriving Typeable
60
62
61
63
instance Eq (TBQueue a ) where
62
- TBQueue a _ _ _ == TBQueue b _ _ _ = a == b
64
+ TBQueue a _ _ _ _ == TBQueue b _ _ _ _ = a == b
63
65
64
66
-- Total channel capacity remaining is CR + CW. Reads only need to
65
67
-- access CR, writes usually need to access only CW but sometimes need
@@ -83,7 +85,7 @@ newTBQueue size = do
83
85
write <- newTVar []
84
86
rsize <- newTVar 0
85
87
wsize <- newTVar size
86
- return (TBQueue rsize read wsize write)
88
+ return (TBQueue rsize read wsize write size )
87
89
88
90
-- | @IO@ version of 'newTBQueue'. This is useful for creating top-level
89
91
-- 'TBQueue's using 'System.IO.Unsafe.unsafePerformIO', because using
@@ -95,11 +97,11 @@ newTBQueueIO size = do
95
97
write <- newTVarIO []
96
98
rsize <- newTVarIO 0
97
99
wsize <- newTVarIO size
98
- return (TBQueue rsize read wsize write)
100
+ return (TBQueue rsize read wsize write size )
99
101
100
102
-- | Write a value to a 'TBQueue'; blocks if the queue is full.
101
103
writeTBQueue :: TBQueue a -> a -> STM ()
102
- writeTBQueue (TBQueue rsize _read wsize write) a = do
104
+ writeTBQueue (TBQueue rsize _read wsize write _size ) a = do
103
105
w <- readTVar wsize
104
106
if (w /= 0 )
105
107
then do writeTVar wsize $! w - 1
@@ -114,7 +116,7 @@ writeTBQueue (TBQueue rsize _read wsize write) a = do
114
116
115
117
-- | Read the next value from the 'TBQueue'.
116
118
readTBQueue :: TBQueue a -> STM a
117
- readTBQueue (TBQueue rsize read _wsize write) = do
119
+ readTBQueue (TBQueue rsize read _wsize write _size ) = do
118
120
xs <- readTVar read
119
121
r <- readTVar rsize
120
122
writeTVar rsize $! r + 1
@@ -143,16 +145,17 @@ tryReadTBQueue c = fmap Just (readTBQueue c) `orElse` return Nothing
143
145
--
144
146
-- @since 2.4.5
145
147
flushTBQueue :: TBQueue a -> STM [a ]
146
- flushTBQueue (TBQueue rsize read wsize write) = do
148
+ flushTBQueue (TBQueue rsize read wsize write size ) = do
147
149
xs <- readTVar read
148
150
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)
156
159
157
160
-- | Get the next value from the @TBQueue@ without removing it,
158
161
-- retrying if the channel is empty.
@@ -176,7 +179,7 @@ tryPeekTBQueue c = do
176
179
-- | Put a data item back onto a channel, where it will be the next item read.
177
180
-- Blocks if the queue is full.
178
181
unGetTBQueue :: TBQueue a -> a -> STM ()
179
- unGetTBQueue (TBQueue rsize read wsize _write) a = do
182
+ unGetTBQueue (TBQueue rsize read wsize _write _size ) a = do
180
183
r <- readTVar rsize
181
184
if (r > 0 )
182
185
then do writeTVar rsize $! r - 1
@@ -188,9 +191,18 @@ unGetTBQueue (TBQueue rsize read wsize _write) a = do
188
191
xs <- readTVar read
189
192
writeTVar read (a: xs)
190
193
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
+
191
203
-- | Returns 'True' if the supplied 'TBQueue' is empty.
192
204
isEmptyTBQueue :: TBQueue a -> STM Bool
193
- isEmptyTBQueue (TBQueue _rsize read _wsize write) = do
205
+ isEmptyTBQueue (TBQueue _rsize read _wsize write _size ) = do
194
206
xs <- readTVar read
195
207
case xs of
196
208
(_: _) -> return False
@@ -203,7 +215,7 @@ isEmptyTBQueue (TBQueue _rsize read _wsize write) = do
203
215
--
204
216
-- @since 2.4.3
205
217
isFullTBQueue :: TBQueue a -> STM Bool
206
- isFullTBQueue (TBQueue rsize _read wsize _write) = do
218
+ isFullTBQueue (TBQueue rsize _read wsize _write _size ) = do
207
219
w <- readTVar wsize
208
220
if (w > 0 )
209
221
then return False
0 commit comments