packages feed

monad-par 0.3.4.7 → 0.3.4.8

raw patch · 5 files changed

+81/−71 lines, 5 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Control.Monad.Par.IO: instance Applicative ParIO
- Control.Monad.Par.IO: instance Functor ParIO
- Control.Monad.Par.IO: instance Monad ParIO
- Control.Monad.Par.IO: instance MonadIO ParIO
- Control.Monad.Par.IO: instance ParFuture IVar ParIO
- Control.Monad.Par.IO: instance ParIVar IVar ParIO
- Control.Monad.Par.Scheds.Direct: activeSessions :: Sched -> HotVar (Set SessionID)
- Control.Monad.Par.Scheds.Direct: idle :: Sched -> HotVar [MVar Bool]
- Control.Monad.Par.Scheds.Direct: instance NFData (IVar a)
- Control.Monad.Par.Scheds.Direct: instance ParFuture IVar Par
- Control.Monad.Par.Scheds.Direct: instance ParIVar IVar Par
- Control.Monad.Par.Scheds.Direct: instance ParUnsafe IVar Par
- Control.Monad.Par.Scheds.Direct: isMain :: Sched -> Bool
- Control.Monad.Par.Scheds.Direct: no :: Sched -> {-# UNPACK #-} !Int
- Control.Monad.Par.Scheds.Direct: rng :: Sched -> HotVar GenIO
- Control.Monad.Par.Scheds.Direct: scheds :: Sched -> [Sched]
- Control.Monad.Par.Scheds.Direct: sessionCounter :: Sched -> HotVar SessionID
- Control.Monad.Par.Scheds.Direct: sessions :: Sched -> HotVar [Session]
- Control.Monad.Par.Scheds.Direct: workpool :: Sched -> WSDeque (Par ())
- Control.Monad.Par.Scheds.Sparks: instance Applicative Par
- Control.Monad.Par.Scheds.Sparks: instance Functor Par
- Control.Monad.Par.Scheds.Sparks: instance Monad Par
- Control.Monad.Par.Scheds.Sparks: instance ParFuture Future Par
- Control.Monad.Par.Scheds.Trace: instance ParFuture IVar Par
- Control.Monad.Par.Scheds.Trace: instance ParIVar IVar Par
- Control.Monad.Par.Scheds.TraceInternal: idle :: Sched -> IORef [MVar Bool]
- Control.Monad.Par.Scheds.TraceInternal: instance Applicative Par
- Control.Monad.Par.Scheds.TraceInternal: instance Eq (IVar a)
- Control.Monad.Par.Scheds.TraceInternal: instance Functor Par
- Control.Monad.Par.Scheds.TraceInternal: instance Monad Par
- Control.Monad.Par.Scheds.TraceInternal: instance NFData (IVar a)
- Control.Monad.Par.Scheds.TraceInternal: no :: Sched -> {-# UNPACK #-} !Int
- Control.Monad.Par.Scheds.TraceInternal: runCont :: Par a -> (a -> Trace) -> Trace
- Control.Monad.Par.Scheds.TraceInternal: scheds :: Sched -> [Sched]
- Control.Monad.Par.Scheds.TraceInternal: workpool :: Sched -> IORef [Trace]
+ Control.Monad.Par.IO: instance Control.Monad.IO.Class.MonadIO Control.Monad.Par.IO.ParIO
+ Control.Monad.Par.IO: instance Control.Monad.Par.Class.ParFuture Control.Monad.Par.Scheds.TraceInternal.IVar Control.Monad.Par.IO.ParIO
+ Control.Monad.Par.IO: instance Control.Monad.Par.Class.ParIVar Control.Monad.Par.Scheds.TraceInternal.IVar Control.Monad.Par.IO.ParIO
+ Control.Monad.Par.IO: instance GHC.Base.Applicative Control.Monad.Par.IO.ParIO
+ Control.Monad.Par.IO: instance GHC.Base.Functor Control.Monad.Par.IO.ParIO
+ Control.Monad.Par.IO: instance GHC.Base.Monad Control.Monad.Par.IO.ParIO
+ Control.Monad.Par.Scheds.Direct: [activeSessions] :: Sched -> HotVar (Set SessionID)
+ Control.Monad.Par.Scheds.Direct: [idle] :: Sched -> HotVar [MVar Bool]
+ Control.Monad.Par.Scheds.Direct: [isMain] :: Sched -> Bool
+ Control.Monad.Par.Scheds.Direct: [no] :: Sched -> {-# UNPACK #-} !Int
+ Control.Monad.Par.Scheds.Direct: [rng] :: Sched -> HotVar GenIO
+ Control.Monad.Par.Scheds.Direct: [scheds] :: Sched -> [Sched]
+ Control.Monad.Par.Scheds.Direct: [sessionCounter] :: Sched -> HotVar SessionID
+ Control.Monad.Par.Scheds.Direct: [sessions] :: Sched -> HotVar [Session]
+ Control.Monad.Par.Scheds.Direct: [workpool] :: Sched -> WSDeque (Par ())
+ Control.Monad.Par.Scheds.Direct: instance Control.DeepSeq.NFData (Control.Monad.Par.Scheds.Direct.IVar a)
+ Control.Monad.Par.Scheds.Direct: instance Control.Monad.Par.Class.ParFuture Control.Monad.Par.Scheds.Direct.IVar Control.Monad.Par.Scheds.DirectInternal.Par
+ Control.Monad.Par.Scheds.Direct: instance Control.Monad.Par.Class.ParIVar Control.Monad.Par.Scheds.Direct.IVar Control.Monad.Par.Scheds.DirectInternal.Par
+ Control.Monad.Par.Scheds.Direct: instance Control.Monad.Par.Unsafe.ParUnsafe Control.Monad.Par.Scheds.Direct.IVar Control.Monad.Par.Scheds.DirectInternal.Par
+ Control.Monad.Par.Scheds.Sparks: instance Control.Monad.Par.Class.ParFuture Control.Monad.Par.Scheds.Sparks.Future Control.Monad.Par.Scheds.Sparks.Par
+ Control.Monad.Par.Scheds.Sparks: instance GHC.Base.Applicative Control.Monad.Par.Scheds.Sparks.Par
+ Control.Monad.Par.Scheds.Sparks: instance GHC.Base.Functor Control.Monad.Par.Scheds.Sparks.Par
+ Control.Monad.Par.Scheds.Sparks: instance GHC.Base.Monad Control.Monad.Par.Scheds.Sparks.Par
+ Control.Monad.Par.Scheds.Trace: instance Control.Monad.Par.Class.ParFuture Control.Monad.Par.Scheds.TraceInternal.IVar Control.Monad.Par.Scheds.TraceInternal.Par
+ Control.Monad.Par.Scheds.Trace: instance Control.Monad.Par.Class.ParIVar Control.Monad.Par.Scheds.TraceInternal.IVar Control.Monad.Par.Scheds.TraceInternal.Par
+ Control.Monad.Par.Scheds.TraceInternal: [idle] :: Sched -> IORef [MVar Bool]
+ Control.Monad.Par.Scheds.TraceInternal: [no] :: Sched -> {-# UNPACK #-} !Int
+ Control.Monad.Par.Scheds.TraceInternal: [runCont] :: Par a -> (a -> Trace) -> Trace
+ Control.Monad.Par.Scheds.TraceInternal: [scheds] :: Sched -> [Sched]
+ Control.Monad.Par.Scheds.TraceInternal: [workpool] :: Sched -> IORef [Trace]
+ Control.Monad.Par.Scheds.TraceInternal: instance Control.DeepSeq.NFData (Control.Monad.Par.Scheds.TraceInternal.IVar a)
+ Control.Monad.Par.Scheds.TraceInternal: instance GHC.Base.Applicative Control.Monad.Par.Scheds.TraceInternal.Par
+ Control.Monad.Par.Scheds.TraceInternal: instance GHC.Base.Functor Control.Monad.Par.Scheds.TraceInternal.Par
+ Control.Monad.Par.Scheds.TraceInternal: instance GHC.Base.Monad Control.Monad.Par.Scheds.TraceInternal.Par
+ Control.Monad.Par.Scheds.TraceInternal: instance GHC.Classes.Eq (Control.Monad.Par.Scheds.TraceInternal.IVar a)

Files

Control/Monad/Par.hs view
@@ -61,7 +61,7 @@   available processors.    Unlike @Control.Parallel@, in @Control.Monad.Par@ parallelism is-  not combined with laziness, so sharing and granulairty are+  not combined with laziness, so sharing and granularity are   completely under the control of the programmer.  New units of   parallel work are only created by @fork@ and a few other   combinators.@@ -97,7 +97,7 @@   runPar, runParIO,    fork,-  -- | forks a computation to happen in parallel.  The forked+  -- | Forks a computation to happen in parallel.  The forked   -- computation may exchange values with other computations using   -- @IVar@s. @@ -105,21 +105,21 @@   IVar,    new, -  -- | creates a new @IVar@+  -- creates a new @IVar@    newFull, -  -- | creates a new @IVar@ that contains a value+  -- creates a new @IVar@ that contains a value    newFull_, -  -- | creates a new @IVar@ that contains a value (head-strict only)+  -- creates a new @IVar@ that contains a value (head-strict only)    get, -  -- | read the value in an @IVar@.  'get' can only return when the+  -- read the value in an @IVar@.  'get' can only return when the   -- value has been written by a prior or parallel @put@ to the same   -- @IVar@.    put, -  -- | put a value into a @IVar@.  Multiple 'put's to the same @IVar@+  -- put a value into an @IVar@.  Multiple 'put's to the same @IVar@   -- are not allowed, and result in a runtime error.   --   -- 'put' fully evaluates its argument, which therefore must be an@@ -132,11 +132,11 @@   --    put_,-  -- | like 'put', but only head-strict rather than fully-strict.+  -- like 'put', but only head-strict rather than fully-strict.    -- * Operations   spawn,-  -- | Like 'fork', but returns a @IVar@ that can be used to query the+  -- | Like 'fork', but returns an @IVar@ that can be used to query the   -- result of the forked computataion.  Therefore @spawn@ provides /futures/ or /promises/.   --   -- >  spawn p = do
Control/Monad/Par/Scheds/Direct.hs view
@@ -205,8 +205,8 @@   mb <- R.tryPopL workpool   when dbg $ case mb of          Nothing -> return ()-	 Just _  -> do sn <- makeStableName mb-	 	       printf " [%d]                                   -> POP work unit %d\n" no (hashStableName sn)+         Just _  -> do sn <- makeStableName mb+                       printf " [%d]                                   -> POP work unit %d\n" no (hashStableName sn)   return mb  {-# INLINE pushWork #-}@@ -214,7 +214,7 @@ pushWork Sched { workpool, idle, no, isMain } task = do   R.pushL workpool task   when dbg $ do sn <- makeStableName task-		printf " [%d]                                   -> PUSH work unit %d\n" no (hashStableName sn)+                printf " [%d]                                   -> PUSH work unit %d\n" no (hashStableName sn) #if  defined(IDLING_ON) && defined(WAKEIDLE)   --when isMain$    -- Experimenting with reducing contention by doing this only from a single thread.                     -- TODO: We need to have a proper binary wakeup-tree.@@ -415,11 +415,11 @@    activeSessions  <- newHotVar S.empty    sessionCounter  <- newHotVar (baseSessionID + 1)    let allscheds = [ Sched { no=x, idle, isMain= (x==main),-			     workpool=wp, scheds=allscheds, rng=rng,+                             workpool=wp, scheds=allscheds, rng=rng,                              sessions = stck,                              activeSessions=activeSessions,                              sessionCounter=sessionCounter-			   }+                           }                    --  | (x,wp,rng,stck) <- zip4 [0..] workpools rngs sessionStacks                    | x   <- [0 .. numCapabilities-1]                    | wp  <- workpools@@ -439,13 +439,13 @@ --------------------------------------------------------------------------------  {-# INLINE new  #-}--- | creates a new @IVar@+-- | Creates a new @IVar@ new :: Par (IVar a) new  = io$ do r <- newIORef Empty               return (IVar r)  {-# INLINE get  #-}--- | read the value in a @IVar@.  The 'get' can only return when the+-- | Read the value in an @IVar@.  The 'get' operation can only return when the -- value has been written by a prior or parallel @put@ to the same -- @IVar@. get (IVar vr) =  do@@ -453,8 +453,8 @@     do        e  <- io$ readIORef vr        case e of-	  Full a -> return a-	  _ -> do+          Full a -> return a+          _ -> do             sch <- RD.ask #  ifdef DEBUG_DIRECT             sn <- io$ makeStableName vr  -- Should probably do the MutVar inside...@@ -462,14 +462,14 @@ #else             let resched = #  endif-			  longjmpSched -- Invariant: kont must not be lost.+                          longjmpSched -- Invariant: kont must not be lost.             -- Because we continue on the same processor the Sched stays the same:             -- TODO: Try NOT using monadic values as first class.  Check for performance effect:-	    r <- io$ atomicModifyIORef vr $ \x -> case x of-		      Empty      -> (Blocked [pushWork sch . kont], resched)-		      Full a     -> (Full a, return a) -- kont is implicit here.-		      Blocked ks -> (Blocked (pushWork sch . kont:ks), resched)-	    r+            r <- io$ atomicModifyIORef vr $ \x -> case x of+                      Empty      -> (Blocked [pushWork sch . kont], resched)+                      Full a     -> (Full a, return a) -- kont is implicit here.+                      Blocked ks -> (Blocked (pushWork sch . kont:ks), resched)+            r  -- | NOTE unsafePeek is NOT exposed directly through this module.  (So -- this module remains SAFE in the Safe Haskell sense.)  It can only@@ -512,13 +512,13 @@    sched <- RD.ask    (ks,res) <- io$ do       pr <- atomicModifyIORef vr $ \e -> case e of-		   Empty      -> (Full content, ([], content))-		   Full x     -> (Full x, ([], x))-		   Blocked ks -> (Full content, (ks, content))+                   Empty      -> (Full content, ([], content))+                   Full x     -> (Full x, ([], x))+                   Blocked ks -> (Full content, (ks, content)) #ifdef DEBUG_DIRECT       sn <- makeStableName vr       printf " [%d] unsafeTryPut: value %s in IVar %d.  Waking up %d continuations.\n"-	     (no sched) (show content) (hashStableName sn) (length (fst pr))+             (no sched) (show content) (hashStableName sn) (length (fst pr)) #endif       return pr    wakeUp sched ks content@@ -615,7 +615,7 @@     Nothing -> do                   (Session _ finRef):_ <- liftIO$ readIORef $ sessions mysched                   fin <- liftIO$ readIORef finRef-		  if fin+                  if fin                    then do when (dbglvl >= 1) $ liftIO $ do                              tid <- myThreadId                              sess <- readSessions mysched@@ -633,22 +633,22 @@                      --     sess <- readSessions mysched                      --     printf " [%d %s]  -    Apparently NOT finished with head session... trying to steal, all sessions %s\n"                      --            (no mysched) (show tid) (show sess)-		     liftIO$ steal mysched+                     liftIO$ steal mysched #ifdef WAKEIDLE --                     io$ tryWakeIdle (idle mysched) #endif                      liftIO yield-		     rescheduleR (cnt+1) kont+                     rescheduleR (cnt+1) kont     Just task -> do        -- When popping work from our own queue the Sched (Reader value) stays the same:        when dbg $ do sn <- liftIO$ makeStableName task-		     liftIO$ printf " [%d] popped work %d from own queue\n" (no mysched) (hashStableName sn)+                     liftIO$ printf " [%d] popped work %d from own queue\n" (no mysched) (hashStableName sn)        let C.ContT fn = unPar task        -- Run the stolen task with a continuation that returns to the scheduler if the task exits normally:        fn (\ _ -> do            sch <- RD.ask            when dbg$ liftIO$ printf "  + task finished successfully on cpu %d, calling reschedule continuation..\n" (no sch)-	   rescheduleR 0 kont)+           rescheduleR 0 kont)   -- | Attempt to steal work or, failing that, give up and go idle.@@ -684,7 +684,7 @@                          return ()                        else do                          when dbg$ printf " [%d]  | woken up\n" my_no-			 i <- getnext (-1::Int)+                         i <- getnext (-1::Int)                          go maxtries i      -- We need to return from this loop to check sessionFinished and exit the scheduler if necessary.@@ -693,7 +693,7 @@     ----------------------------------------     go tries i       | i == my_no = do i' <- getnext i-			go (tries-1) i'+                        go (tries-1) i'        | otherwise     = do          -- We ONLY go through the global sched array to access victims:@@ -707,16 +707,16 @@          case r of            Just task  -> do               when dbg$ do sn <- makeStableName task-			   printf " [%d]  | stole work (unit %d) from cpu %d\n" my_no (hashStableName sn) (no schd)-	      runReaderWith mysched $-		C.runContT (unPar task)-		 (\_ -> do-		   when dbg$ do sn <- liftIO$ makeStableName task-		                liftIO$ printf " [%d]  | DONE running stolen work (unit %d) from %d\n" my_no (hashStableName sn) (no schd)-		   return ())+                           printf " [%d]  | stole work (unit %d) from cpu %d\n" my_no (hashStableName sn) (no schd)+              runReaderWith mysched $+                C.runContT (unPar task)+                 (\_ -> do+                   when dbg$ do sn <- liftIO$ makeStableName task+                                liftIO$ printf " [%d]  | DONE running stolen work (unit %d) from %d\n" my_no (hashStableName sn) (no schd)+                   return ())             Nothing -> do i' <- getnext i-			 go (tries-1) i'+                         go (tries-1) i'  -- | The continuation which should not be called. errK :: t@@ -728,7 +728,7 @@ --                trace (str ++" trivialCont evaluated!")                 liftIO$ printf " !! trivialCont evaluated, msg: %s\n" str #endif-		return ()+                return ()  ---------------------------------------------------------------------------------------------------- @@ -749,8 +749,8 @@  -- The following is usually inefficient! newFull_ a = do v <- new-		put_ v a-		return v+                put_ v a+                return v  newFull a = deepseq a (newFull_ a) @@ -813,7 +813,7 @@  #ifdef NEW_GENERIC instance PU.ParMonad Par where-  fork = fork  +  fork = fork   internalLiftIO io = Par (lift $ lift io)  instance PU.ParThreadSafe Par where@@ -826,14 +826,14 @@   spawn  = spawn   spawn_ = spawn_   spawnP = spawnP-  + instance PN.ParIVar Par  where   new  = new   put_ = put_   newFull = newFull   newFull_ = newFull_ #endif-   + -- </boilerplate> -------------------------------------------------------------------------------- @@ -898,7 +898,7 @@                        _ -> do                                putStrLn$"CAUGHT child thread exception: "++show e                                return ()-		    )+                    )            action  @@ -909,14 +909,14 @@    forkit $ do       tid <- myThreadId       E.catch action-	 (\ e ->+         (\ e ->            case E.fromException e of              Just E.ThreadKilled -> printf -- hPrintf stderr                                     "\nThreadKilled exception inside child thread, %s (not propagating!): %s\n" (show tid) (show descr)-	     _  -> do printf -- hPrintf stderr+             _  -> do printf -- hPrintf stderr                         "\nException inside child thread %s, %s: %s\n" (show descr) (show tid) (show e)                       E.throwTo parent (e :: E.SomeException)-	 )+         )   -- Do all the memory reads to snapshot the current session stack:@@ -925,5 +925,3 @@   ls <- readIORef (sessions sched)   bools <- mapM (\ (Session _ r) -> readIORef r) ls   return (zip (map (\ (Session sid _) -> sid) ls) bools)--
Control/Monad/Par/Scheds/Sparks.hs view
@@ -55,7 +55,7 @@ -- <boilerplate>  instance Monad Par where-  return x = Done x+  return = pure   Done x >>= k = k x  instance PC.ParFuture Future Par  where @@ -69,7 +69,7 @@  instance Applicative Par where    (<*>) = ap-   pure  = return+   pure  = Done  #ifdef NEW_GENERIC doio :: IO a -> Par a
Control/Monad/Par/Scheds/TraceInternal.hs view
@@ -25,9 +25,12 @@ import Control.Concurrent hiding (yield) import GHC.Conc (numCapabilities) import Control.DeepSeq-import Control.Applicative -- import Text.Printf +#if !MIN_VERSION_base(4,8,0)+import Control.Applicative+#endif+ #if __GLASGOW_HASKELL__ <= 700 import GHC.Conc (forkOnIO) forkOn = forkOnIO@@ -74,22 +77,22 @@          loop parent     Done ->          if _doSync-	 then reschedule queue+         then reschedule queue -- We could fork an extra thread here to keep numCapabilities workers -- even when the main thread returns to the runPar caller...          else do putStrLn " [par] Forking replacement thread..\n"                  forkIO (reschedule queue); return () -- But even if we don't we are not orphaning any work in this -- threads work-queue because it can be stolen by other threads.---	 else return ()+--       else return ()      Yield parent -> do         -- Go to the end of the worklist:         let Sched { workpool } = queue         -- TODO: Perhaps consider Data.Seq here.-	-- This would also be a chance to steal and work from opposite ends of the queue.+        -- This would also be a chance to steal and work from opposite ends of the queue.         atomicModifyIORef workpool $ \ts -> (ts++[parent], ())-	reschedule queue+        reschedule queue     LiftIO io c -> do         r <- io         loop (c r)@@ -172,12 +175,12 @@     fmap f m = Par $ \c -> runCont m (c . f)  instance Monad Par where-    return a = Par ($ a)+    return = pure     m >>= k  = Par $ \c -> runCont m $ \a -> runCont (k a) c  instance Applicative Par where    (<*>) = ap-   pure  = return+   pure a = Par ($ a)  newtype IVar a = IVar (IORef (IVarContents a)) -- data IVar a = IVar (IORef (IVarContents a))@@ -247,11 +250,20 @@      _ -> error "no result"  +-- | Run a parallel, deterministic computation and return its result.+-- +--   Note: you must NOT return an IVar in the output of the parallel+--   computation.  This is unfortunately not enforced, as it is with+--   `runST` or with newer libraries that export a Par monad, such as+--   `lvish`. runPar :: Par a -> a runPar = unsafePerformIO . runPar_internal True  -- | A version that avoids an internal `unsafePerformIO` for calling --   contexts that are already in the `IO` monad.+--+--   Returning any value containing IVar is still disallowed, as it+--   can compromise type safety. runParIO :: Par a -> IO a runParIO = runPar_internal True @@ -263,29 +275,29 @@  -- ----------------------------------------------------------------------------- --- | creates a new @IVar@+-- | Creates a new @IVar@ new :: Par (IVar a) new  = Par $ New Empty --- | creates a new @IVar@ that contains a value+-- | Creates a new @IVar@ that contains a value newFull :: NFData a => a -> Par (IVar a) newFull x = deepseq x (Par $ New (Full x)) --- | creates a new @IVar@ that contains a value (head-strict only)+-- | Creates a new @IVar@ that contains a value (head-strict only) newFull_ :: a -> Par (IVar a) newFull_ !x = Par $ New (Full x) --- | read the value in a @IVar@.  The 'get' can only return when the+-- | Read the value in an @IVar@.  The 'get' operation can only return when the -- value has been written by a prior or parallel @put@ to the same -- @IVar@. get :: IVar a -> Par a get v = Par $ \c -> Get v c --- | like 'put', but only head-strict rather than fully-strict.+-- | Like 'put', but only head-strict rather than fully-strict. put_ :: IVar a -> a -> Par () put_ v !a = Par $ \c -> Put v a (c ()) --- | put a value into a @IVar@.  Multiple 'put's to the same @IVar@+-- | Put a value into an @IVar@.  Multiple 'put's to the same @IVar@ -- are not allowed, and result in a runtime error. -- -- 'put' fully evaluates its argument, which therefore must be an
monad-par.cabal view
@@ -1,5 +1,5 @@ Name:                monad-par-Version:             0.3.4.7+Version:             0.3.4.8 Synopsis:            A library for parallel programming based on a monad