packages feed

concurrency 1.2.3.0 → 1.3.0.0

raw patch · 8 files changed

+224/−92 lines, 8 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Control.Concurrent.Classy.Async: asyncBound :: MonadConc m => m a -> m (Async m a)
+ Control.Concurrent.Classy.Async: asyncBoundN :: MonadConc m => String -> m a -> m (Async m a)
+ Control.Concurrent.Classy.Async: withAsyncBound :: MonadConc m => m a -> (Async m a -> m b) -> m b
+ Control.Concurrent.Classy.Async: withAsyncBoundN :: MonadConc m => String -> m a -> (Async m a -> m b) -> m b
+ Control.Monad.Conc.Class: forkOS :: MonadConc m => m () -> m (ThreadId m)
+ Control.Monad.Conc.Class: forkOSN :: MonadConc m => String -> m () -> m (ThreadId m)
+ Control.Monad.Conc.Class: runInBoundThread :: MonadConc m => m a -> m a
+ Control.Monad.Conc.Class: runInUnboundThread :: MonadConc m => m a -> m a
- Control.Monad.Conc.Class: class (Applicative m, Monad m, MonadCatch m, MonadThrow m, MonadMask m, MonadSTM (STM m), Ord (ThreadId m), Show (ThreadId m)) => MonadConc m where type STM m :: * -> * type MVar m :: * -> * type CRef m :: * -> * type Ticket m :: * -> * type ThreadId m :: * fork ma = forkWithUnmask (const ma) forkWithUnmask = forkWithUnmaskN "" forkWithUnmaskN _ = forkWithUnmask forkOn c ma = forkOnWithUnmask c (const ma) forkOnWithUnmask = forkOnWithUnmaskN "" forkOnWithUnmaskN _ = forkOnWithUnmask threadDelay _ = yield newEmptyMVar = newEmptyMVarN "" newEmptyMVarN _ = newEmptyMVar newCRef = newCRefN "" newCRefN _ = newCRef readCRef cref = readForCAS cref >>= peekTicket atomicWriteCRef r a = atomicModifyCRef r $ const (a, ()) modifyCRefCAS_ cref f = modifyCRefCAS cref (\ a -> (f a, ())) readTVarConc = atomically . readTVar where {
+ Control.Monad.Conc.Class: class (Applicative m, Monad m, MonadCatch m, MonadThrow m, MonadMask m, MonadSTM (STM m), Ord (ThreadId m), Show (ThreadId m)) => MonadConc m where {
- Control.Monad.STM.Class: class (MonadCatch stm, MonadPlus stm) => MonadSTM stm where type TVar stm :: * -> * newTVar = newTVarN "" newTVarN _ = newTVar where {
+ Control.Monad.STM.Class: class (MonadCatch stm, MonadPlus stm) => MonadSTM stm where {

Files

CHANGELOG.markdown view
@@ -7,6 +7,36 @@ *de facto* standard Haskell versioning scheme.  +1.3.0.0+-------++- **Date**    2017-12-23+- **Git tag** [concurrency-1.3.0.0][]+- **Hackage** https://hackage.haskell.org/package/concurrency-1.3.0.0++### Control.Concurrent.Classy.Async++- New `asyncBound`, `asyncBoundN`, `withAsyncBound`, and `withAsyncBoundN` functions for doing+  asynchronous actions on bound threads. (#126)++### Control.Monad.Conc.Class++- `MonadConc` now supports bound threads with new `forkOS`, `forkOSN`, and `isCurrentThreadBound`+  functions. (#126)++- New `runInBoundThread` and `runInUnboundThread` functions. (#126)++- The `rtsSupportsBoundThreads` definition is now the definition from Control.Concurrent+  re-exported, not just `False`. (#126)++Note that bound threads are only supported if you compile with GHC and link with -threaded.++[concurrency-1.3.0.0]: https://github.com/barrucadu/dejafu/releases/tag/concurrency-1.3.0.0+++---------------------------------------------------------------------------------------------------++ 1.2.3.0 ------- 
Control/Concurrent/Classy/Async.hs view
@@ -1,7 +1,15 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE RankNTypes #-} --- | This module is a version of the+-- |+-- Module      : Control.Concurrent.Classy.Async+-- Copyright   : (c) 2016--2017 Michael Walker+-- License     : MIT+-- Maintainer  : Michael Walker <mike@barrucadu.co.uk>+-- Stability   : stable+-- Portability : CPP, RankNTypes+--+-- This module is a version of the -- <https://hackage.haskell.org/package/async async> package. It -- provides a set of operations for running @MonadConc@ operations -- asynchronously and waiting for their results.@@ -18,14 +26,9 @@ -- The 'withAsync' function starts an operation in a separate thread, -- and kills it if the inner action finishes before it completes. ----- There are a few deviations from the regular async package:------   * 'asyncBound' and 'withAsyncBound' are missing as @MonadConc@---   does not support bound threads.------   * The @Alternative@ instance for 'Concurrently' uses @forever---   yield@ in the definition of @empty@, rather than @forever---   (threadDelay maxBound)@.+-- Unlike the regular async package, the @Alternative@ instance for+-- 'Concurrently' uses @forever yield@ in the definition of @empty@,+-- rather than @forever (threadDelay maxBound)@. module Control.Concurrent.Classy.Async   ( -- * Asynchronous actions     Async@@ -33,6 +36,8 @@   -- * Spawning   , async   , asyncN+  , asyncBound+  , asyncBoundN   , asyncOn   , asyncOnN   , asyncWithUnmask@@ -43,6 +48,8 @@   -- * Spawning with automatic 'cancel'ation   , withAsync   , withAsyncN+  , withAsyncBound+  , withAsyncBoundN   , withAsyncOn   , withAsyncOnN   , withAsyncWithUnmask@@ -192,6 +199,19 @@ asyncN :: MonadConc m => String -> m a -> m (Async m a) asyncN name = asyncUsing (forkN name) +-- | Like 'async' but uses 'forkOS' internally.+--+-- @since 1.3.0.0+asyncBound :: MonadConc m => m a -> m (Async m a)+asyncBound = asyncUsing forkOS++-- | Like 'asyncBound', but using a named thread for better debugging+-- information.+--+-- @since 1.3.0.0+asyncBoundN :: MonadConc m => String -> m a -> m (Async m a)+asyncBoundN name = asyncUsing (forkOSN name)+ -- | Like 'async' but using 'forkOn' internally. -- -- @since 1.1.1.0@@ -265,6 +285,19 @@ -- @since 1.2.3.0 withAsyncN :: MonadConc m => String -> m a -> (Async m a -> m b) -> m b withAsyncN name = withAsyncUsing (forkN name)++-- | Like 'withAsync' but uses 'forkOS' internally.+--+-- @since 1.3.0.0+withAsyncBound :: MonadConc m => m a -> (Async m a -> m b) -> m b+withAsyncBound = withAsyncUsing forkOS++-- | Like 'withAsyncBound' but using a named thread for better+-- debugging information.+--+-- @since 1.3.0.0+withAsyncBoundN :: MonadConc m => String -> m a -> (Async m a -> m b) -> m b+withAsyncBoundN name = withAsyncUsing (forkOSN name)  -- | Like 'withAsync' but uses 'forkOn' internally. --
Control/Concurrent/Classy/CRef.hs view
@@ -48,28 +48,28 @@   --   -- We can see this by testing with different memory models:   ---  -- > > autocheck' SequentialConsistency crefs-  -- > [pass] Never Deadlocks (checked: 6)-  -- > [pass] No Exceptions (checked: 6)-  -- > [fail] Consistent Result (checked: 5)-  -- >         (False,True) S0-------S1-----S0--S2-----S0----  -- >         (True,False) S0-------S1-P2-----S1----S0-----  -- >         (True,True) S0-------S1--P2-----S1---S0-----  -- >         (False,True) S0-------S1---P2-----S1--S0-----  -- >         (True,False) S0-------S2-----S1-----S0-----  -- >         ...+  -- > > autocheckWay defaultWay SequentialConsistency relaxed+  -- > [pass] Never Deadlocks+  -- > [pass] No Exceptions+  -- > [fail] Consistent Result+  -- >        (False,True) S0---------S1----S0--S2----S0--+  -- >+  -- >        (True,True) S0---------S1-P2----S1---S0---+  -- >+  -- >        (True,False) S0---------S2----S1----S0---   -- > False   ---  -- > > autocheck' TotalStoreOrder crefs-  -- > [pass] Never Deadlocks (checked: 303)-  -- > [pass] No Exceptions (checked: 303)-  -- > [fail] Consistent Result (checked: 302)-  -- >         (False,True) S0-------S1-----C-S0--S2-----C-S0----  -- >         (True,False) S0-------S1-P2-----C-S1----S0-----  -- >         (True,True) S0-------S1-P2--C-S1----C-S0--S2---S0----  -- >         (False,True) S0-------S1-P2--P1--C-C-S1--S0--S2---S0----  -- >         (False,False) S0-------S1-P2--P1----S2---C-C-S0-----  -- >         ...+  -- > > autocheckWay defaultWay TotalStoreOrder  relaxed+  -- > [pass] Never Deadlocks+  -- > [pass] No Exceptions+  -- > [fail] Consistent Result+  -- >         (False,True) S0---------S1----S0--S2----S0--+  -- >+  -- >         (False,False) S0---------S1--P2----S1--S0---+  -- >+  -- >         (True,False) S0---------S2----S1----S0---+  -- >+  -- >         (True,True) S0---------S1-C-S2----S1---S0---   -- > False   --   -- Traces for non-sequentially-consistent memory models show where
Control/Monad/Conc/Class.hs view
@@ -8,7 +8,7 @@  -- | -- Module      : Control.Monad.Conc.Class--- Copyright   : (c) 2016 Michael Walker+-- Copyright   : (c) 2016--2017 Michael Walker -- License     : MIT -- Maintainer  : Michael Walker <mike@barrucadu.co.uk> -- Stability   : experimental@@ -17,16 +17,16 @@ -- This module captures in a typeclass the interface of concurrency -- monads. ----- __Deviations:__ An instance of @MonadConc@ is not required to be--- an instance of @MonadFix@, unlike @IO@. The @CRef@, @MVar@, and+-- __Deviations:__ An instance of @MonadConc@ is not required to be an+-- instance of @MonadFix@, unlike @IO@. The @CRef@, @MVar@, and -- @Ticket@ types are not required to be instances of @Show@ or @Eq@, -- unlike their normal counterparts. The @threadCapability@, -- @threadWaitRead@, @threadWaitWrite@, @threadWaitReadSTM@, -- @threadWaitWriteSTM@, and @mkWeakThreadId@ functions are not -- provided. The @threadDelay@ function is not required to delay the--- thread, merely to yield it. Bound threads are not supported. The--- @BlockedIndefinitelyOnMVar@ (and similar) exceptions are /not/--- thrown during testing, so do not rely on them at all.+-- thread, merely to yield it. The @BlockedIndefinitelyOnMVar@ (and+-- similar) exceptions are /not/ thrown during testing, so do not rely+-- on them at all. module Control.Monad.Conc.Class   ( MonadConc(..) @@ -35,18 +35,31 @@   , forkFinally   , killThread +  -- ** Bound threads++  -- | Support for multiple operating system threads and bound threads+  -- as described below is currently only available in the GHC runtime+  -- system if you use the -threaded option when linking.+  --+  -- Other Haskell systems do not currently support multiple operating+  -- system threads.+  --+  -- A bound thread is a haskell thread that is bound to an operating+  -- system thread. While the bound thread is still scheduled by the+  -- Haskell run-time system, the operating system thread takes care+  -- of all the foreign calls made by the bound thread.+  --+  -- To a foreign library, the bound thread will look exactly like an+  -- ordinary operating system thread created using OS functions like+  -- pthread_create or CreateThread.+  , IO.rtsSupportsBoundThreads+  , runInBoundThread+  , runInUnboundThread+   -- ** Named Threads   , forkN   , forkOnN -  -- ** Bound Threads--  -- | @MonadConc@ does not support bound threads, if you need that-  -- sort of thing you will have to use regular @IO@.--  , rtsSupportsBoundThreads-  , isCurrentThreadBound-   -- * Exceptions   , throw   , catch@@ -109,7 +122,7 @@ -- Every @MonadConc@ has an associated 'MonadSTM', transactions of -- which can be run atomically. ----- @since 1.0.0.0+-- @since 1.3.0.0 class ( Applicative m, Monad m       , MonadCatch m, MonadThrow m, MonadMask m       , MonadSTM (STM m)@@ -118,6 +131,8 @@   {-# MINIMAL         (forkWithUnmask | forkWithUnmaskN)       , (forkOnWithUnmask | forkOnWithUnmaskN)+      , (forkOS | forkOSN)+      , isCurrentThreadBound       , getNumCapabilities       , setNumCapabilities       , myThreadId@@ -194,10 +209,6 @@   -- | Like 'forkWithUnmask', but the thread is given a name which may   -- be used to present more useful debugging information.   ---  -- If an empty name is given, the @ThreadId@ is used. If names-  -- conflict, successive threads with the same name are given a-  -- numeric suffix, counting up from 1.-  --   -- > forkWithUnmaskN _ = forkWithUnmask   --   -- @since 1.0.0.0@@ -234,6 +245,35 @@   forkOnWithUnmaskN :: String -> Int -> ((forall a. m a -> m a) -> m ()) -> m (ThreadId m)   forkOnWithUnmaskN _ = forkOnWithUnmask +  -- | Fork a computation to happen in a /bound thread/, which is+  -- necessary if you need to call foreign (non-Haskell) libraries+  -- that make use of thread-local state, such as OpenGL.+  --+  -- > forkOS = forkOSN ""+  --+  -- @since 1.3.0.0+  forkOS :: m () -> m (ThreadId m)+  forkOS = forkOSN ""++  -- | Like 'forkOS', but the thread is given a name which may be used+  -- to present more useful debugging information.+  --+  -- > forkOSN _ = forkOS+  --+  -- @since 1.3.0.0+  forkOSN :: String -> m () -> m (ThreadId m)+  forkOSN _ = forkOS++  -- | Returns 'True' if the calling thread is bound, that is, if it+  -- is safe to use foreign libraries that rely on thread-local state+  -- from the calling thread.+  --+  -- This will always be false if your program is not compiled with+  -- the threaded runtime.+  --+  -- @since 1.3.0.0+  isCurrentThreadBound :: m Bool+   -- | Get the number of Haskell threads that can run simultaneously.   --   -- @since 1.0.0.0@@ -249,8 +289,7 @@   -- @since 1.0.0.0   myThreadId :: m (ThreadId m) -  -- | Allows a context-switch to any other currently runnable thread-  -- (if any).+  -- | Allows a context-switch to any other unblocked thread (if any).   --   -- @since 1.0.0.0   yield :: m ()@@ -279,10 +318,6 @@   -- | Create a new empty @MVar@, but it is given a name which may be   -- used to present more useful debugging information.   ---  -- If an empty name is given, a counter starting from 0 is used. If-  -- names conflict, successive @MVar@s with the same name are given a-  -- numeric suffix, counting up from 1.-  --   -- > newEmptyMVarN _ = newEmptyMVar   --   -- @since 1.0.0.0@@ -343,10 +378,6 @@   -- | Create a new reference, but it is given a name which may be   -- used to present more useful debugging information.   ---  -- If an empty name is given, a counter starting from 0 is used. If-  -- names conflict, successive @CRef@s with the same name are given a-  -- numeric suffix, counting up from 1.-  --   -- > newCRefN _ = newCRef   --   -- @since 1.0.0.0@@ -479,10 +510,6 @@ -- | Like 'fork', but the thread is given a name which may be used to -- present more useful debugging information. ----- If no name is given, the @ThreadId@ is used. If names conflict,--- successive threads with the same name are given a numeric suffix,--- counting up from 1.--- -- @since 1.0.0.0 forkN :: MonadConc m => String -> m () -> m (ThreadId m) forkN name ma = forkWithUnmaskN name (const ma)@@ -490,28 +517,58 @@ -- | Like 'forkOn', but the thread is given a name which may be used -- to present more useful debugging information. ----- If no name is given, the @ThreadId@ is used. If names conflict,--- successive threads with the same name are given a numeric suffix,--- counting up from 1.--- -- @since 1.0.0.0 forkOnN :: MonadConc m => String -> Int -> m () -> m (ThreadId m) forkOnN name i ma = forkOnWithUnmaskN name i (const ma) --- Bound Threads---- | Provided for compatibility, always returns 'False'.+-- | Run the computation passed as the first argument.  If the calling+-- thread is not /bound/, a bound thread is created temporarily.+-- @runInBoundThread@ doesn't finish until the inner computation+-- finishes. ----- @since 1.0.0.0-rtsSupportsBoundThreads :: Bool-rtsSupportsBoundThreads = False+-- You can wrap a series of foreign function calls that rely on+-- thread-local state with @runInBoundThread@ so that you can use them+-- without knowing whether the current thread is /bound/.+--+-- @since 1.3.0.0+runInBoundThread :: MonadConc m => m a -> m a+runInBoundThread =+  runInThread (not <$> isCurrentThreadBound) (forkOSN "runInBoundThread") --- | Provided for compatibility, always returns 'False'.+-- | Run the computation passed as the first argument. If the calling+-- thread is /bound/, an unbound thread is created temporarily using+-- @fork@.  @runInBoundThread@ doesn't finish until the inner+-- computation finishes. ----- @since 1.0.0.0-isCurrentThreadBound :: MonadConc m => m Bool-isCurrentThreadBound = pure False+-- Use this function /only/ in the rare case that you have actually+-- observed a performance loss due to the use of bound threads. A+-- program that doesn't need its main thread to be bound and makes+-- /heavy/ use of concurrency (e.g. a web server), might want to wrap+-- its @main@ action in @runInUnboundThread@.+--+-- Note that exceptions which are thrown to the current thread are+-- thrown in turn to the thread that is executing the given+-- computation. This ensures there's always a way of killing the+-- forked thread.+--+-- @since 1.3.0.0+runInUnboundThread :: MonadConc m => m a -> m a+runInUnboundThread =+  runInThread isCurrentThreadBound (forkN "runInUnboundThread") +-- | Helper for 'runInBoundThread' and 'runInUnboundThread'+runInThread :: MonadConc m => m Bool -> (m () -> m (ThreadId m)) -> m a -> m a+runInThread check dofork action = do+  flag <- check+  if flag+    then do+      mv <- newEmptyMVar+      mask $ \restore -> do+        tid <- dofork $ Ca.try (restore action) >>= putMVar mv+        let wait = takeMVar mv `catch` \(e :: SomeException) -> throwTo tid e >> wait+        wait >>= either (\(e :: SomeException) -> throw e) pure+    else action+ -- Exceptions  -- | Throw an exception. This will \"bubble up\" looking for an@@ -575,10 +632,6 @@ -- | Create a new @MVar@ containing a value, but it is given a name -- which may be used to present more useful debugging information. ----- If no name is given, a counter starting from 0 is used. If names--- conflict, successive @MVar@s with the same name are given a numeric--- suffix, counting up from 1.--- -- @since 1.0.0.0 newMVarN :: MonadConc m => String -> a -> m (MVar m a) newMVarN n a = do@@ -620,10 +673,15 @@    fork   = IO.forkIO   forkOn = IO.forkOn+  forkOS = IO.forkOS    forkWithUnmask   = IO.forkIOWithUnmask   forkOnWithUnmask = IO.forkOnWithUnmask +  forkOSN n ma = forkOS $ do+    labelMe n+    ma+   forkWithUnmaskN n ma = forkWithUnmask $ \umask -> do     labelMe n     ma umask@@ -632,6 +690,8 @@     labelMe n     ma umask +  isCurrentThreadBound = IO.isCurrentThreadBound+   getNumCapabilities = IO.getNumCapabilities   setNumCapabilities = IO.setNumCapabilities   readMVar           = IO.readMVar@@ -698,11 +758,16 @@   fork     ma = toIsConc (fork     $ unIsConc ma)   forkOn i ma = toIsConc (forkOn i $ unIsConc ma) +  forkOS    ma = toIsConc (forkOS    $ unIsConc ma)+  forkOSN n ma = toIsConc (forkOSN n $ unIsConc ma)+   forkWithUnmask        ma = toIsConc (forkWithUnmask        (\umask -> unIsConc $ ma (\mx -> toIsConc (umask $ unIsConc mx))))   forkWithUnmaskN   n   ma = toIsConc (forkWithUnmaskN   n   (\umask -> unIsConc $ ma (\mx -> toIsConc (umask $ unIsConc mx))))   forkOnWithUnmask    i ma = toIsConc (forkOnWithUnmask    i (\umask -> unIsConc $ ma (\mx -> toIsConc (umask $ unIsConc mx))))   forkOnWithUnmaskN n i ma = toIsConc (forkOnWithUnmaskN n i (\umask -> unIsConc $ ma (\mx -> toIsConc (umask $ unIsConc mx)))) +  isCurrentThreadBound = toIsConc isCurrentThreadBound+   getNumCapabilities = toIsConc getNumCapabilities   setNumCapabilities = toIsConc . setNumCapabilities   myThreadId         = toIsConc myThreadId@@ -744,11 +809,16 @@                                                                  \   fork   = liftedF F fork                                      ; \   forkOn = liftedF F . forkOn                                  ; \+  forkOS = liftedF F forkOS                                    ; \                                                                  \+  forkOSN = liftedF F . forkOSN                                ; \+                                                                 \   forkWithUnmask        = liftedFork F forkWithUnmask          ; \   forkWithUnmaskN   n   = liftedFork F (forkWithUnmaskN   n  ) ; \   forkOnWithUnmask    i = liftedFork F (forkOnWithUnmask    i) ; \   forkOnWithUnmaskN n i = liftedFork F (forkOnWithUnmaskN n i) ; \+                                                                 \+  isCurrentThreadBound = lift isCurrentThreadBound             ; \                                                                  \   getNumCapabilities = lift getNumCapabilities                 ; \   setNumCapabilities = lift . setNumCapabilities               ; \
Control/Monad/STM/Class.hs view
@@ -5,7 +5,7 @@  -- | -- Module      : Control.Monad.STM.Class--- Copyright   : (c) 2016 Michael Walker+-- Copyright   : (c) 2016--2017 Michael Walker -- License     : MIT -- Maintainer  : Michael Walker <mike@barrucadu.co.uk> -- Stability   : experimental
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2015, Michael Walker <mike@barrucadu.co.uk>+Copyright (c) 2016--2017, Michael Walker <mike@barrucadu.co.uk>  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the
README.markdown view
@@ -3,16 +3,15 @@  A typeclass abstraction over much of Control.Concurrent (and some extras!). If you're looking for a general introduction to Haskell-concurrency, you should check out the excellent-[Parallel and Concurrent Programming in Haskell][parconc], by Simon-Marlow. If you are already familiar with concurrent Haskell, just-change all the imports from Control.Concurrent.* to-Control.Concurrent.Classy.* and fix the type errors.+concurrency, you should check out the excellent [Parallel and+Concurrent Programming in Haskell][parconc], by Simon Marlow. If you+are already familiar with concurrent Haskell, just change all the+imports from Control.Concurrent.* to Control.Concurrent.Classy.* and+fix the type errors.  A brief list of supported functionality: -- Threads: the `forkIO*` and `forkOn*` functions, although bound-  threads are not supported.+- Threads: both unbound and bound. - Getting and setting capablities. - Yielding and delaying. - Mutable state: STM, `MVar`, and `IORef`.
concurrency.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                concurrency-version:             1.2.3.0+version:             1.3.0.0 synopsis:            Typeclasses, functions, and data types for concurrency and STM.  description:@@ -19,7 +19,7 @@ license-file:        LICENSE author:              Michael Walker maintainer:          mike@barrucadu.co.uk--- copyright:           +copyright:           (c) 2016--2017 Michael Walker category:            Concurrency build-type:          Simple extra-source-files:  README.markdown CHANGELOG.markdown@@ -32,7 +32,7 @@ source-repository this   type:     git   location: https://github.com/barrucadu/dejafu.git-  tag:      concurrency-1.2.3.0+  tag:      concurrency-1.3.0.0  library   exposed-modules:     Control.Monad.Conc.Class