packages feed

dejafu 0.5.1.0 → 0.5.1.1

raw patch · 4 files changed

+74/−52 lines, 4 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ Test.DejaFu.Conc.Internal: Single :: ThreadAction -> Act
+ Test.DejaFu.Conc.Internal: SubC :: SeqTrace -> (Maybe (ThreadId, ThreadAction)) -> Act
+ Test.DejaFu.Conc.Internal: data Act
+ Test.DejaFu.Conc.Internal: instance GHC.Classes.Eq Test.DejaFu.Conc.Internal.Act
+ Test.DejaFu.Conc.Internal: instance GHC.Show.Show Test.DejaFu.Conc.Internal.Act
- Test.DejaFu.Conc.Internal: runConcurrency :: MonadRef r n => Scheduler g -> MemType -> g -> Int -> M n r a -> n (Either Failure a, g, SeqTrace)
+ Test.DejaFu.Conc.Internal: runConcurrency :: MonadRef r n => Scheduler g -> MemType -> g -> Int -> M n r a -> n (Either Failure a, g, SeqTrace, Maybe (ThreadId, ThreadAction))
- Test.DejaFu.Conc.Internal: runThreads :: MonadRef r n => Scheduler g -> MemType -> r (Maybe (Either Failure a)) -> Context n r g -> n (Context n r g, SeqTrace)
+ Test.DejaFu.Conc.Internal: runThreads :: MonadRef r n => Scheduler g -> MemType -> r (Maybe (Either Failure a)) -> Context n r g -> n (Context n r g, SeqTrace, Maybe (ThreadId, ThreadAction))
- Test.DejaFu.Conc.Internal: stepThread :: forall n r g. MonadRef r n => Scheduler g -> MemType -> ThreadId -> Action n r -> Context n r g -> n (Either Failure (Context n r g, Either (ThreadAction, SeqTrace) ThreadAction))
+ Test.DejaFu.Conc.Internal: stepThread :: forall n r g. MonadRef r n => Scheduler g -> MemType -> ThreadId -> Action n r -> Context n r g -> n (Either Failure (Context n r g), Act)

Files

Test/DejaFu/Conc.hs view
@@ -177,7 +177,7 @@               -> Conc n r a               -> n (Either Failure a, s, Trace) runConcurrent sched memtype s ma = do-  (res, s', trace) <- runConcurrency sched memtype s 2 (unC ma)+  (res, s', trace, _) <- runConcurrency sched memtype s 2 (unC ma)   pure (res, s', F.toList trace)  -- | Run a concurrent computation and return its result.
Test/DejaFu/Conc/Internal.hs view
@@ -53,7 +53,7 @@                -> g                -> Int                -> M n r a-               -> n (Either Failure a, g, SeqTrace)+               -> n (Either Failure a, g, SeqTrace, Maybe (ThreadId, ThreadAction)) runConcurrency sched memtype g caps ma = do   ref <- newRef Nothing @@ -61,9 +61,9 @@   let threads = launch' Unmasked initialThread (const c) M.empty   let ctx = Context { cSchedState = g, cIdSource = initialIdSource, cThreads = threads, cWriteBuf = emptyBuffer, cCaps = caps } -  (finalCtx, trace) <- runThreads sched memtype ref ctx+  (finalCtx, trace, finalAction) <- runThreads sched memtype ref ctx   out <- readRef ref-  pure (fromJust out, cSchedState finalCtx, trace)+  pure (fromJust out, cSchedState finalCtx, trace, finalAction)  -- | The context a collection of threads are running in. data Context n r g = Context@@ -76,25 +76,36 @@  -- | Run a collection of threads, until there are no threads left. runThreads :: MonadRef r n-           => Scheduler g -> MemType -> r (Maybe (Either Failure a)) -> Context n r g -> n (Context n r g, SeqTrace)+           => Scheduler g -> MemType -> r (Maybe (Either Failure a)) -> Context n r g -> n (Context n r g, SeqTrace, Maybe (ThreadId, ThreadAction)) runThreads sched memtype ref = go Seq.empty [] Nothing where   -- sofar is the 'SeqTrace', sofarSched is the @[(Decision,   -- ThreadAction)]@ trace the scheduler needs.   go sofar sofarSched prior ctx-    | isTerminated  = stop ctx-    | isDeadlocked  = die Deadlock ctx-    | isSTMLocked   = die STMDeadlock ctx-    | isAborted     = die Abort $ ctx { cSchedState = g' }-    | isNonexistant = die InternalError $ ctx { cSchedState = g' }-    | isBlocked     = die InternalError $ ctx { cSchedState = g' }+    | isTerminated  = stop prior ctx+    | isDeadlocked  = die prior Deadlock ctx+    | isSTMLocked   = die prior STMDeadlock ctx+    | isAborted     = die prior Abort $ ctx { cSchedState = g' }+    | isNonexistant = die prior InternalError $ ctx { cSchedState = g' }+    | isBlocked     = die prior InternalError $ ctx { cSchedState = g' }     | otherwise = do       stepped <- stepThread sched memtype chosen (_continuation $ fromJust thread) $ ctx { cSchedState = g' }       case stepped of-        Right (ctx', actOrTrc) -> loop actOrTrc ctx'-        Left UncaughtException-          | chosen == initialThread -> die UncaughtException $ ctx { cSchedState = g' }-          | otherwise -> loop (Right Killed) $ ctx { cThreads = kill chosen threadsc, cSchedState = g' }-        Left failure -> die failure $ ctx { cSchedState = g' }+        (Right ctx', actOrTrc) ->+          let (sofar', sofarSched', prior', ctx'') = setupNext actOrTrc ctx'+          in go sofar' sofarSched' prior' ctx''+        (Left UncaughtException, actOrTrc)+          | chosen == initialThread ->+              let ctx' = ctx { cSchedState = g' }+                  (_, _, prior', ctx'') = setupNext actOrTrc ctx'+              in die prior' UncaughtException ctx''+          | otherwise ->+              let ctx' = ctx { cThreads = kill chosen threadsc, cSchedState = g' }+                  (sofar', sofarSched', prior', ctx'') = setupNext actOrTrc ctx'+              in go sofar' sofarSched' prior' ctx''+        (Left failure, actOrTrc) ->+          let ctx' = ctx { cSchedState = g' }+              (_, _, prior', ctx'') = setupNext actOrTrc ctx'+          in die prior' failure ctx''      where       (choice, g')  = sched sofarSched prior (fromList $ map (\(t,l:|_) -> (t,l)) runnable') (cSchedState ctx)@@ -127,24 +138,34 @@        nextActions t = lookahead . _continuation . fromJust $ M.lookup t threadsc -      stop finalCtx = pure (finalCtx, sofar)-      die reason finalCtx = writeRef ref (Just $ Left reason) >> stop finalCtx+      stop finalDecision finalCtx = pure (finalCtx, sofar, finalDecision)+      die finalDecision reason finalCtx = writeRef ref (Just $ Left reason) >> stop finalDecision finalCtx -      loop trcOrAct ctx' =+      setupNext trcOrAct ctx' =         let (act, trc) = case trcOrAct of-              Left (a, as) -> (a, (decision, runnable', a) <| as)-              Right a      -> (a, Seq.singleton (decision, runnable', a))+              Single a    -> (a, Seq.singleton (decision, runnable', a))+              SubC   as _ -> (Subconcurrency, (decision, runnable', Subconcurrency) <| as)             threads' = if (interruptible <$> M.lookup chosen (cThreads ctx')) /= Just False                        then unblockWaitingOn chosen (cThreads ctx')                        else cThreads ctx'             sofar' = sofar <> trc             sofarSched' = sofarSched <> map (\(d,_,a) -> (d,a)) (F.toList trc)-            prior' = Just (chosen, act)-        in go sofar' sofarSched' prior' $ ctx' { cThreads = delCommitThreads threads' }+            prior' = case trcOrAct of+              Single _ -> Just (chosen, act)+              SubC _ finalD -> finalD+        in (sofar', sofarSched', prior', ctx' { cThreads = delCommitThreads threads' })  -------------------------------------------------------------------------------- -- * Single-step execution +-- | What a thread did.+data Act+  = Single ThreadAction+  -- ^ Just one action.+  | SubC SeqTrace (Maybe (ThreadId, ThreadAction))+  -- ^ Subconcurrency, with the given trace and final action.+  deriving (Eq, Show)+ -- | Run a single thread one step, by dispatching on the type of -- 'Action'. stepThread :: forall n r g. MonadRef r n@@ -158,13 +179,13 @@   -- ^ Action to step   -> Context n r g   -- ^ The execution context.-  -> n (Either Failure (Context n r g, Either (ThreadAction, SeqTrace) ThreadAction))+  -> n (Either Failure (Context n r g), Act) stepThread sched memtype tid action ctx = case action of     -- start a new thread, assigning it the next 'ThreadId'-    AFork n a b -> pure . Right $+    AFork n a b -> pure $         let threads' = launch tid newtid a (cThreads ctx)             (idSource', newtid) = nextTId n (cIdSource ctx)-        in (ctx { cThreads = goto (b newtid) tid threads', cIdSource = idSource' }, Right (Fork newtid))+        in (Right ctx { cThreads = goto (b newtid) tid threads', cIdSource = idSource' }, Single (Fork newtid))      -- get the 'ThreadId' of the current thread     AMyTId c -> simple (goto (c tid) tid (cThreads ctx)) MyThreadId@@ -173,8 +194,8 @@     AGetNumCapabilities c -> simple (goto (c (cCaps ctx)) tid (cThreads ctx)) $ GetNumCapabilities (cCaps ctx)      -- set the number of capabilities-    ASetNumCapabilities i c -> pure . Right $-      (ctx { cThreads = goto c tid (cThreads ctx), cCaps = i }, Right (SetNumCapabilities i))+    ASetNumCapabilities i c -> pure+      (Right ctx { cThreads = goto c tid (cThreads ctx), cCaps = i }, Single (SetNumCapabilities i))      -- yield the current thread     AYield c -> simple (goto c tid (cThreads ctx)) Yield@@ -184,7 +205,7 @@       let (idSource', newmvid) = nextMVId n (cIdSource ctx)       ref <- newRef Nothing       let mvar = MVar newmvid ref-      pure $ Right (ctx { cThreads = goto (c mvar) tid (cThreads ctx), cIdSource = idSource' }, Right (NewMVar newmvid))+      pure (Right ctx { cThreads = goto (c mvar) tid (cThreads ctx), cIdSource = idSource' }, Single (NewMVar newmvid))      -- put a value into a @MVar@, blocking the thread until it's empty.     APutMVar cvar@(MVar cvid _) a c -> synchronised $ do@@ -224,7 +245,7 @@       let (idSource', newcrid) = nextCRId n (cIdSource ctx)       ref <- newRef (M.empty, 0, a)       let cref = CRef newcrid ref-      pure $ Right (ctx { cThreads = goto (c cref) tid (cThreads ctx), cIdSource = idSource' }, Right (NewCRef newcrid))+      pure (Right ctx { cThreads = goto (c cref) tid (cThreads ctx), cIdSource = idSource' }, Single (NewCRef newcrid))      -- read from a @CRef@.     AReadCRef cref@(CRef crid _) c -> do@@ -258,11 +279,11 @@       -- add to buffer using thread id.       TotalStoreOrder -> do         wb' <- bufferWrite (cWriteBuf ctx) (tid, Nothing) cref a-        pure $ Right (ctx { cThreads = goto c tid (cThreads ctx), cWriteBuf = wb' }, Right (WriteCRef crid))+        pure (Right ctx { cThreads = goto c tid (cThreads ctx), cWriteBuf = wb' }, Single (WriteCRef crid))       -- add to buffer using both thread id and cref id       PartialStoreOrder -> do         wb' <- bufferWrite (cWriteBuf ctx) (tid, Just crid) cref a-        pure $ Right (ctx { cThreads = goto c tid (cThreads ctx), cWriteBuf = wb' }, Right (WriteCRef crid))+        pure (Right ctx { cThreads = goto c tid (cThreads ctx), cWriteBuf = wb' }, Single (WriteCRef crid))      -- perform a compare-and-swap on a @CRef@.     ACasCRef cref@(CRef crid _) tick a c -> synchronised $ do@@ -279,7 +300,7 @@         TotalStoreOrder -> commitWrite (cWriteBuf ctx) (t, Nothing)         -- commit using the cref id.         PartialStoreOrder -> commitWrite (cWriteBuf ctx) (t, Just c)-      pure $ Right (ctx { cWriteBuf = wb' }, Right (CommitCRef t c))+      pure (Right ctx { cWriteBuf = wb' }, Single (CommitCRef t c))      -- run a STM transaction atomically.     AAtom stm c -> synchronised $ do@@ -287,15 +308,16 @@       case res of         Success _ written val ->           let (threads', woken) = wake (OnTVar written) (cThreads ctx)-          in pure $ Right (ctx { cThreads = goto (c val) tid threads', cIdSource = idSource' }, Right (STM trace woken))+          in pure (Right ctx { cThreads = goto (c val) tid threads', cIdSource = idSource' }, Single (STM trace woken))         Retry touched ->           let threads' = block (OnTVar touched) tid (cThreads ctx)-          in pure $ Right (ctx { cThreads = threads', cIdSource = idSource'}, Right (BlockedSTM trace))+          in pure (Right ctx { cThreads = threads', cIdSource = idSource'}, Single (BlockedSTM trace))         Exception e -> do-          res' <- stepThrow e+          let act = STM trace []+          res' <- stepThrow act e           pure $ case res' of-            Right (ctx', _) -> Right (ctx' { cIdSource = idSource' }, Right Throw)-            Left err -> Left err+            (Right ctx', _) -> (Right ctx' { cIdSource = idSource' }, Single act)+            (Left err, _) -> (Left err, Single act)      -- lift an action from the underlying monad into the @Conc@     -- computation.@@ -305,7 +327,7 @@      -- throw an exception, and propagate it to the appropriate     -- handler.-    AThrow e -> stepThrow e+    AThrow e -> stepThrow Throw e      -- throw an exception to the target thread, and propagate it to     -- the appropriate handler.@@ -317,7 +339,7 @@              | interruptible thread -> case propagate (toException e) t threads' of                Just threads'' -> simple threads'' $ ThrowTo t                Nothing-                 | t == initialThread -> pure $ Left UncaughtException+                 | t == initialThread -> pure (Left UncaughtException, Single (ThrowTo t))                  | otherwise -> simple (kill t threads') $ ThrowTo t              | otherwise -> simple blocked $ BlockedThrowTo t            Nothing -> simple threads' $ ThrowTo t@@ -359,10 +381,10 @@      -- run a subconcurrent computation.     ASub ma c-      | M.size (cThreads ctx) > 1 -> pure (Left IllegalSubconcurrency)+      | M.size (cThreads ctx) > 1 -> pure (Left IllegalSubconcurrency, Single Subconcurrency)       | otherwise -> do-          (res, g', trace) <- runConcurrency sched memtype (cSchedState ctx) (cCaps ctx) ma-          pure $ Right (ctx { cThreads = goto (AStopSub (c res)) tid (cThreads ctx), cSchedState = g' }, Left (Subconcurrency, trace))+          (res, g', trace, finalDecision) <- runConcurrency sched memtype (cSchedState ctx) (cCaps ctx) ma+          pure (Right ctx { cThreads = goto (AStopSub (c res)) tid (cThreads ctx), cSchedState = g' }, SubC trace finalDecision)      -- after the end of a subconcurrent computation. does nothing,     -- only exists so that: there is an entry in the trace for@@ -373,19 +395,19 @@      -- this is not inline in the long @case@ above as it's needed by     -- @AAtom@, @AThrow@, and @AThrowTo@.-    stepThrow e =+    stepThrow act e =       case propagate (toException e) tid (cThreads ctx) of-        Just threads' -> simple threads' Throw-        Nothing -> pure $ Left UncaughtException+        Just threads' -> simple threads' act+        Nothing -> pure (Left UncaughtException, Single act)      -- helper for actions which only change the threads.-    simple threads' act = pure $ Right (ctx { cThreads = threads' }, Right act)+    simple threads' act = pure (Right ctx { cThreads = threads' }, Single act)      -- helper for actions impose a write barrier.     synchronised ma = do       writeBarrier (cWriteBuf ctx)       res <- ma -      return $ case res of-        Right (ctx', act) -> Right (ctx' { cWriteBuf = emptyBuffer }, act)+      pure $ case res of+        (Right ctx', act) -> (Right ctx' { cWriteBuf = emptyBuffer }, act)         _ -> res
Test/DejaFu/SCT/Internal.hs view
@@ -167,7 +167,7 @@                    , dporTodo  = M.delete tid' (dporTodo dpor)                    , dporDone  = done                    }-  grow _ _ [] dpor = dpor+  grow _ _ [] _ = err "incorporateTrace" "trace exhausted without reading a to-do point!"    -- Construct a new subtree corresponding to a trace suffix.   subtree state tid sleep ((_, _, a):rest) =
dejafu.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                dejafu-version:             0.5.1.0+version:             0.5.1.1 synopsis:            Systematic testing for Haskell concurrency.  description:@@ -74,7 +74,7 @@ source-repository this   type:     git   location: https://github.com/barrucadu/dejafu.git-  tag:      dejafu-0.5.1.0+  tag:      dejafu-0.5.1.1  library   exposed-modules:     Test.DejaFu