Skip to content

Commit 98c2a83

Browse files
committed
Simplify and optimise Barrier
1 parent 0aa6ccc commit 98c2a83

File tree

2 files changed

+8
-19
lines changed

2 files changed

+8
-19
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
Changelog for Extra
22

3+
Simplify and optimise Barrier
34
Mark modules that are empty as DEPRECATED
45
Remove support for GHC 7.10
56
1.7.1, released 2020-03-10

src/Control/Concurrent/Extra.hs

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -182,38 +182,26 @@ withVar (Var x) f = withMVar x f
182182
-- for it to complete. A barrier has similarities to a future or promise
183183
-- from other languages, has been known as an IVar in other Haskell work,
184184
-- and in some ways is like a manually managed thunk.
185-
newtype Barrier a = Barrier (Var (Either (MVar ()) a))
186-
-- Either a Left empty MVar you should wait or a Right result
187-
-- With base 4.7 and above readMVar is atomic so you probably can implement Barrier directly on MVar a
185+
newtype Barrier a = Barrier (MVar a)
188186

189187
-- | Create a new 'Barrier'.
190188
newBarrier :: IO (Barrier a)
191-
newBarrier = fmap Barrier $ newVar . Left =<< newEmptyMVar
189+
newBarrier = Barrier <$> newEmptyMVar
192190

193191
-- | Write a value into the Barrier, releasing anyone at 'waitBarrier'.
194192
-- Any subsequent attempts to signal the 'Barrier' will throw an exception.
195193
signalBarrier :: Partial => Barrier a -> a -> IO ()
196-
signalBarrier (Barrier var) v = mask_ $ -- use mask so never in an inconsistent state
197-
join $ modifyVar var $ \x -> case x of
198-
Left bar -> pure (Right v, putMVar bar ())
199-
Right res -> error "Control.Concurrent.Extra.signalBarrier, attempt to signal a barrier that has already been signaled"
194+
signalBarrier (Barrier var) v = do
195+
b <- tryPutMVar var v
196+
unless b $ errorIO "Control.Concurrent.Extra.signalBarrier, attempt to signal a barrier that has already been signaled"
200197

201198

202199
-- | Wait until a barrier has been signaled with 'signalBarrier'.
203200
waitBarrier :: Barrier a -> IO a
204-
waitBarrier (Barrier var) = do
205-
x <- readVar var
206-
case x of
207-
Right res -> pure res
208-
Left bar -> do
209-
readMVar bar
210-
x <- readVar var
211-
case x of
212-
Right res -> pure res
213-
Left bar -> error "Control.Concurrent.Extra, internal invariant violated in Barrier"
201+
waitBarrier (Barrier var) = readMVar var
214202

215203

216204
-- | A version of 'waitBarrier' that never blocks, returning 'Nothing'
217205
-- if the barrier has not yet been signaled.
218206
waitBarrierMaybe :: Barrier a -> IO (Maybe a)
219-
waitBarrierMaybe (Barrier bar) = eitherToMaybe <$> readVar bar
207+
waitBarrierMaybe (Barrier bar) = tryReadMVar bar

0 commit comments

Comments
 (0)