Skip to content

Commit eeed986

Browse files
committed
Optimize peekTQueue and peekTBQueue
Reduce the amount of operations, avoiding redundant writes and hence reducing the chance of conflicts
1 parent 5f4d7c6 commit eeed986

File tree

2 files changed

+28
-8
lines changed

2 files changed

+28
-8
lines changed

Control/Concurrent/STM/TBQueue.hs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,20 @@ flushTBQueue (TBQueue rsize read wsize write size) = do
161161
-- | Get the next value from the @TBQueue@ without removing it,
162162
-- retrying if the channel is empty.
163163
peekTBQueue :: TBQueue a -> STM a
164-
peekTBQueue c = do
165-
x <- readTBQueue c
166-
unGetTBQueue c x
167-
return x
164+
peekTBQueue (TBQueue _ read _ write _) = do
165+
xs <- readTVar read
166+
case xs of
167+
(x:_) -> return x
168+
[] -> do
169+
ys <- readTVar write
170+
case ys of
171+
[] -> retry
172+
_ -> do
173+
let (z:zs) = reverse ys -- NB. lazy: we want the transaction to be
174+
-- short, otherwise it will conflict
175+
writeTVar write []
176+
writeTVar read zs
177+
return z
168178

169179
-- | A version of 'peekTBQueue' which does not retry. Instead it
170180
-- returns @Nothing@ if no value is available.

Control/Concurrent/STM/TQueue.hs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,20 @@ flushTQueue (TQueue read write) = do
122122
-- | Get the next value from the @TQueue@ without removing it,
123123
-- retrying if the channel is empty.
124124
peekTQueue :: TQueue a -> STM a
125-
peekTQueue c = do
126-
x <- readTQueue c
127-
unGetTQueue c x
128-
return x
125+
peekTQueue (TQueue read write) = do
126+
xs <- readTVar read
127+
case xs of
128+
(x:_) -> return x
129+
[] -> do
130+
ys <- readTVar write
131+
case ys of
132+
[] -> retry
133+
_ -> do
134+
let (z:zs) = reverse ys -- NB. lazy: we want the transaction to be
135+
-- short, otherwise it will conflict
136+
writeTVar write []
137+
writeTVar read zs
138+
return z
129139

130140
-- | A version of 'peekTQueue' which does not retry. Instead it
131141
-- returns @Nothing@ if no value is available.

0 commit comments

Comments
 (0)