@@ -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
5455data 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
6163instance 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.
101103writeTBQueue :: 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'.
116118readTBQueue :: 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
145147flushTBQueue :: 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.
178181unGetTBQueue :: 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.
192204isEmptyTBQueue :: 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
205217isFullTBQueue :: 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