[Git][ghc/ghc][master] Update `Control.Concurrent.*` documentation
Marge Bot (@marge-bot)
gitlab at gitlab.haskell.org
Tue Aug 22 16:32:26 UTC 2023
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
4ba088d1 by konsumlamm at 2023-08-22T12:32:02-04:00
Update `Control.Concurrent.*` documentation
- - - - -
5 changed files:
- libraries/base/Control/Concurrent/Chan.hs
- libraries/base/Control/Concurrent/MVar.hs
- libraries/base/Control/Concurrent/QSem.hs
- libraries/base/Control/Concurrent/QSemN.hs
- libraries/base/GHC/MVar.hs
Changes:
=====================================
libraries/base/Control/Concurrent/Chan.hs
=====================================
@@ -13,9 +13,9 @@
--
-- Unbounded channels.
--
--- The channels are implemented with @MVar at s and therefore inherit all the
+-- The channels are implemented with 'Control.Concurrent.MVar's and therefore inherit all the
-- caveats that apply to @MVar at s (possibility of races, deadlocks etc). The
--- stm (software transactional memory) library has a more robust implementation
+-- @stm@ (software transactional memory) library has a more robust implementation
-- of channels called @TChan at s.
--
-----------------------------------------------------------------------------
@@ -43,7 +43,7 @@ import Control.Exception (mask_)
#define _UPK_(x) {-# UNPACK #-} !(x)
-- A channel is represented by two @MVar at s keeping track of the two ends
--- of the channel contents,i.e., the read- and write ends. Empty @MVar at s
+-- of the channel contents, i.e., the read- and write ends. Empty @MVar at s
-- are used to handle consumers trying to read from an empty channel.
-- |'Chan' is an abstract type representing an unbounded FIFO channel.
@@ -59,13 +59,13 @@ data ChItem a = ChItem a _UPK_(Stream a)
-- although it leads to higher allocation, the channel data takes up
-- less space and is therefore quicker to GC.
--- See the Concurrent Haskell paper for a diagram explaining the
+-- See the Concurrent Haskell paper for a diagram explaining
-- how the different channel operations proceed.
-- @newChan@ sets up the read and write end of a channel by initialising
-- these two @MVar at s with an empty @MVar at .
--- |Build and returns a new instance of 'Chan'.
+-- |Build and return a new instance of 'Chan'.
newChan :: IO (Chan a)
newChan = do
hole <- newEmptyMVar
@@ -113,7 +113,7 @@ readChan (Chan readVar _) =
return (new_read_end, val)
-- |Duplicate a 'Chan': the duplicate channel begins empty, but data written to
--- either channel from then on will be available from both. Hence this creates
+-- either channel from then on will be available from both. Hence this creates
-- a kind of broadcast channel, where data written by anyone is seen by
-- everyone else.
--
=====================================
libraries/base/Control/Concurrent/MVar.hs
=====================================
@@ -11,7 +11,7 @@
-- Stability : stable
-- Portability : non-portable (concurrency)
--
--- An @'MVar' t@ is mutable location that is either empty or contains a
+-- An @'MVar' t@ is a mutable location that is either empty or contains a
-- value of type @t at . It has two fundamental operations: 'putMVar'
-- which fills an 'MVar' if it is empty and blocks otherwise, and
-- 'takeMVar' which empties an 'MVar' if it is full and blocks
@@ -25,7 +25,7 @@
-- wait and signal.
--
-- They were introduced in the paper
--- <https://www.haskell.org/ghc/docs/papers/concurrent-haskell.ps.gz "Concurrent Haskell">
+-- ["Concurrent Haskell"](https://www.microsoft.com/en-us/research/wp-content/uploads/1996/01/concurrent-haskell.pdf)
-- by Simon Peyton Jones, Andrew Gordon and Sigbjorn Finne, though
-- some details of their implementation have since then changed (in
-- particular, a put on a full 'MVar' used to error, but now merely
@@ -35,7 +35,7 @@
--
-- 'MVar's offer more flexibility than 'Data.IORef.IORef's, but less flexibility
-- than 'GHC.Conc.STM'. They are appropriate for building synchronization
--- primitives and performing simple interthread communication; however
+-- primitives and performing simple inter-thread communication; however
-- they are very simple and susceptible to race conditions, deadlocks or
-- uncaught exceptions. Do not use them if you need to perform larger
-- atomic operations such as reading from multiple variables: use 'GHC.Conc.STM'
@@ -54,8 +54,8 @@
-- No thread can be blocked indefinitely on an 'MVar' unless another
-- thread holds that 'MVar' indefinitely. One usual implementation of
-- this fairness guarantee is that threads blocked on an 'MVar' are
--- served in a first-in-first-out fashion, but this is not guaranteed
--- in the semantics.
+-- served in a first-in-first-out fashion (this is what GHC does),
+-- but this is not guaranteed in the semantics.
--
-- === Gotchas
--
@@ -64,7 +64,7 @@
-- 'MVar', it will be evaluated by the thread that consumes it, not the
-- thread that produced it. Be sure to 'evaluate' values to be placed
-- in an 'MVar' to the appropriate normal form, or utilize a strict
--- MVar provided by the strict-concurrency package.
+-- @MVar@ provided by the [strict-concurrency](https://hackage.haskell.org/package/strict-concurrency) package.
--
-- === Ordering
--
@@ -89,33 +89,33 @@
-- reader has not read yet, and empty otherwise.
--
-- @
--- data SkipChan a = SkipChan (MVar (a, [MVar ()])) (MVar ())
+-- data SkipChan a = SkipChan (MVar (a, [MVar ()])) (MVar ())
--
--- newSkipChan :: IO (SkipChan a)
--- newSkipChan = do
--- sem <- newEmptyMVar
--- main <- newMVar (undefined, [sem])
--- return (SkipChan main sem)
+-- newSkipChan :: IO (SkipChan a)
+-- newSkipChan = do
+-- sem <- newEmptyMVar
+-- main <- newMVar (undefined, [sem])
+-- return (SkipChan main sem)
--
--- putSkipChan :: SkipChan a -> a -> IO ()
--- putSkipChan (SkipChan main _) v = do
--- (_, sems) <- takeMVar main
--- putMVar main (v, [])
--- mapM_ (\sem -> putMVar sem ()) sems
+-- putSkipChan :: SkipChan a -> a -> IO ()
+-- putSkipChan (SkipChan main _) v = do
+-- (_, sems) <- takeMVar main
+-- putMVar main (v, [])
+-- mapM_ (\\sem -> putMVar sem ()) sems
--
--- getSkipChan :: SkipChan a -> IO a
--- getSkipChan (SkipChan main sem) = do
--- takeMVar sem
--- (v, sems) <- takeMVar main
--- putMVar main (v, sem:sems)
--- return v
+-- getSkipChan :: SkipChan a -> IO a
+-- getSkipChan (SkipChan main sem) = do
+-- takeMVar sem
+-- (v, sems) <- takeMVar main
+-- putMVar main (v, sem : sems)
+-- return v
--
--- dupSkipChan :: SkipChan a -> IO (SkipChan a)
--- dupSkipChan (SkipChan main _) = do
--- sem <- newEmptyMVar
--- (v, sems) <- takeMVar main
--- putMVar main (v, sem:sems)
--- return (SkipChan main sem)
+-- dupSkipChan :: SkipChan a -> IO (SkipChan a)
+-- dupSkipChan (SkipChan main _) = do
+-- sem <- newEmptyMVar
+-- (v, sems) <- takeMVar main
+-- putMVar main (v, sem : sems)
+-- return (SkipChan main sem)
-- @
--
-- This example was adapted from the original Concurrent Haskell paper.
@@ -186,7 +186,7 @@ swapMVar mvar new =
-}
{-# INLINE withMVar #-}
-- inlining has been reported to have dramatic effects; see
--- http://www.haskell.org//pipermail/haskell/2006-May/017907.html
+-- https://mail.haskell.org/pipermail/haskell/2006-May/017907.html
withMVar :: MVar a -> (a -> IO b) -> IO b
withMVar m io =
mask $ \restore -> do
@@ -274,7 +274,7 @@ addMVarFinalizer :: MVar a -> IO () -> IO ()
addMVarFinalizer = GHC.MVar.addMVarFinalizer
-- | Make a 'Weak' pointer to an 'MVar', using the second argument as
--- a finalizer to run when 'MVar' is garbage-collected
+-- a finalizer to run when the 'MVar' is garbage-collected
--
-- @since 4.6.0.0
mkWeakMVar :: MVar a -> IO () -> IO (Weak (MVar a))
=====================================
libraries/base/Control/Concurrent/QSem.hs
=====================================
@@ -34,7 +34,7 @@ import Data.Maybe
--
-- The pattern
--
--- > bracket_ waitQSem signalQSem (...)
+-- > bracket_ waitQSem signalQSem (...)
--
-- is safe; it never loses a unit of the resource.
--
@@ -67,7 +67,7 @@ newQSem initial
sem <- newMVar (initial, [], [])
return (QSem sem)
--- |Wait for a unit to become available
+-- |Wait for a unit to become available.
waitQSem :: QSem -> IO ()
waitQSem (QSem m) =
mask_ $ do
@@ -91,7 +91,7 @@ waitQSem (QSem m) =
else do putMVar b (); return (i,b1,b2)
putMVar m r')
--- |Signal that a unit of the 'QSem' is available
+-- |Signal that a unit of the 'QSem' is available.
signalQSem :: QSem -> IO ()
signalQSem (QSem m) =
uninterruptibleMask_ $ do -- Note [signal uninterruptible]
=====================================
libraries/base/Control/Concurrent/QSemN.hs
=====================================
@@ -32,12 +32,12 @@ import Data.IORef (IORef, newIORef, atomicModifyIORef)
import System.IO.Unsafe (unsafePerformIO)
-- | 'QSemN' is a quantity semaphore in which the resource is acquired
--- and released in units of one. It provides guaranteed FIFO ordering
+-- and released in arbitrary amounts. It provides guaranteed FIFO ordering
-- for satisfying blocked `waitQSemN` calls.
--
-- The pattern
--
--- > bracket_ (waitQSemN n) (signalQSemN n) (...)
+-- > bracket_ (waitQSemN n) (signalQSemN n) (...)
--
-- is safe; it never loses any of the resource.
--
@@ -71,7 +71,7 @@ newQSemN initial
-- An unboxed version of Maybe (MVar a)
data MaybeMV a = JustMV !(MVar a) | NothingMV
--- |Wait for the specified quantity to become available
+-- |Wait for the specified quantity to become available.
waitQSemN :: QSemN -> Int -> IO ()
-- We need to mask here. Once we've enqueued our MVar, we need
-- to be sure to wait for it. Otherwise, we could lose our
=====================================
libraries/base/GHC/MVar.hs
=====================================
@@ -42,9 +42,11 @@ as a box, which may be empty or full.
-}
-- pull in Eq (Mvar a) too, to avoid GHC.Conc being an orphan-instance module
--- | @since 4.1.0.0
+-- | Compares the underlying pointers.
+--
+-- @since 4.1.0.0
instance Eq (MVar a) where
- (MVar mvar1#) == (MVar mvar2#) = isTrue# (sameMVar# mvar1# mvar2#)
+ (MVar mvar1#) == (MVar mvar2#) = isTrue# (sameMVar# mvar1# mvar2#)
{-
M-Vars are rendezvous points for concurrent threads. They begin
@@ -66,9 +68,9 @@ newEmptyMVar = IO $ \ s# ->
-- |Create an 'MVar' which contains the supplied value.
newMVar :: a -> IO (MVar a)
-newMVar value =
- newEmptyMVar >>= \ mvar ->
- putMVar mvar value >>
+newMVar value = do
+ mvar <- newEmptyMVar
+ putMVar mvar value
return mvar
-- |Return the contents of the 'MVar'. If the 'MVar' is currently
@@ -95,6 +97,7 @@ takeMVar (MVar mvar#) = IO $ \ s# -> takeMVar# mvar# s#
--
-- 'readMVar' is multiple-wakeup, so when multiple readers are
-- blocked on an 'MVar', all of them are woken up at the same time.
+-- The runtime guarantees that all woken threads complete their 'readMVar' operation.
--
-- /Compatibility note:/ Prior to base 4.7, 'readMVar' was a combination
-- of 'takeMVar' and 'putMVar'. This mean that in the presence of
@@ -104,12 +107,12 @@ takeMVar (MVar mvar#) = IO $ \ s# -> takeMVar# mvar# s#
-- can be recovered by implementing 'readMVar as follows:
--
-- @
--- readMVar :: MVar a -> IO a
--- readMVar m =
--- mask_ $ do
--- a <- takeMVar m
--- putMVar m a
--- return a
+-- readMVar :: MVar a -> IO a
+-- readMVar m =
+-- mask_ $ do
+-- a <- takeMVar m
+-- putMVar m a
+-- return a
-- @
readMVar :: MVar a -> IO a
readMVar (MVar mvar#) = IO $ \ s# -> readMVar# mvar# s#
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/4ba088d19dd35859fe0dc5ba47e994e8e2d46efb
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/4ba088d19dd35859fe0dc5ba47e994e8e2d46efb
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20230822/35e2623f/attachment-0001.html>
More information about the ghc-commits
mailing list