module Test.DejaFu.Schedule
(
Scheduler(..)
, randomSched
, roundRobinSched
, randomSchedNP
, roundRobinSchedNP
, makeNonPreemptive
) where
import Data.List.NonEmpty (NonEmpty(..), toList)
import System.Random (RandomGen, randomR)
import Test.DejaFu.Internal
import Test.DejaFu.Types
newtype Scheduler state = Scheduler
{ forall state.
Scheduler state
-> Maybe (ThreadId, ThreadAction)
-> NonEmpty (ThreadId, Lookahead)
-> ConcurrencyState
-> state
-> (Maybe ThreadId, state)
scheduleThread
:: Maybe (ThreadId, ThreadAction)
-> NonEmpty (ThreadId, Lookahead)
-> ConcurrencyState
-> state
-> (Maybe ThreadId, state)
}
randomSched :: RandomGen g => Scheduler g
randomSched :: forall g. RandomGen g => Scheduler g
randomSched = forall state.
(Maybe (ThreadId, ThreadAction)
-> NonEmpty (ThreadId, Lookahead)
-> ConcurrencyState
-> state
-> (Maybe ThreadId, state))
-> Scheduler state
Scheduler forall {b} {p} {a} {b} {p}.
RandomGen b =>
p -> NonEmpty (a, b) -> p -> b -> (Maybe a, b)
go where
go :: p -> NonEmpty (a, b) -> p -> b -> (Maybe a, b)
go p
_ NonEmpty (a, b)
threads p
_ b
g =
let threads' :: [a]
threads' = forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst (forall a. NonEmpty a -> [a]
toList NonEmpty (a, b)
threads)
(Int
choice, b
g') = forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (Int
0, forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
threads' forall a. Num a => a -> a -> a
- Int
1) b
g
in (forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a. HasCallStack => [a] -> Int -> a
eidx [a]
threads' Int
choice, b
g')
roundRobinSched :: Scheduler ()
roundRobinSched :: Scheduler ()
roundRobinSched = forall state.
(Maybe (ThreadId, ThreadAction)
-> NonEmpty (ThreadId, Lookahead)
-> ConcurrencyState
-> state
-> (Maybe ThreadId, state))
-> Scheduler state
Scheduler forall {a} {b} {b} {p} {p}.
Ord a =>
Maybe (a, b) -> NonEmpty (a, b) -> p -> p -> (Maybe a, ())
go where
go :: Maybe (a, b) -> NonEmpty (a, b) -> p -> p -> (Maybe a, ())
go Maybe (a, b)
Nothing ((a
tid,b
_):|[(a, b)]
_) p
_ p
_ = (forall a. a -> Maybe a
Just a
tid, ())
go (Just (a
prior, b
_)) NonEmpty (a, b)
threads p
_ p
_ =
let threads' :: [a]
threads' = forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst (forall a. NonEmpty a -> [a]
toList NonEmpty (a, b)
threads)
candidates :: [a]
candidates =
if a
prior forall a. Ord a => a -> a -> Bool
>= forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [a]
threads'
then [a]
threads'
else forall a. (a -> Bool) -> [a] -> [a]
filter (forall a. Ord a => a -> a -> Bool
>a
prior) [a]
threads'
in (forall a. a -> Maybe a
Just (forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [a]
candidates), ())
randomSchedNP :: RandomGen g => Scheduler g
randomSchedNP :: forall g. RandomGen g => Scheduler g
randomSchedNP = forall s. Scheduler s -> Scheduler s
makeNonPreemptive forall g. RandomGen g => Scheduler g
randomSched
roundRobinSchedNP :: Scheduler ()
roundRobinSchedNP :: Scheduler ()
roundRobinSchedNP = forall s. Scheduler s -> Scheduler s
makeNonPreemptive Scheduler ()
roundRobinSched
makeNonPreemptive :: Scheduler s -> Scheduler s
makeNonPreemptive :: forall s. Scheduler s -> Scheduler s
makeNonPreemptive Scheduler s
sched = forall state.
(Maybe (ThreadId, ThreadAction)
-> NonEmpty (ThreadId, Lookahead)
-> ConcurrencyState
-> state
-> (Maybe ThreadId, state))
-> Scheduler state
Scheduler Maybe (ThreadId, ThreadAction)
-> NonEmpty (ThreadId, Lookahead)
-> ConcurrencyState
-> s
-> (Maybe ThreadId, s)
newsched where
newsched :: Maybe (ThreadId, ThreadAction)
-> NonEmpty (ThreadId, Lookahead)
-> ConcurrencyState
-> s
-> (Maybe ThreadId, s)
newsched p :: Maybe (ThreadId, ThreadAction)
p@(Just (ThreadId
prior, ThreadAction
_)) NonEmpty (ThreadId, Lookahead)
threads ConcurrencyState
cs s
s
| ThreadId
prior forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst (forall a. NonEmpty a -> [a]
toList NonEmpty (ThreadId, Lookahead)
threads) = (forall a. a -> Maybe a
Just ThreadId
prior, s
s)
| Bool
otherwise = forall state.
Scheduler state
-> Maybe (ThreadId, ThreadAction)
-> NonEmpty (ThreadId, Lookahead)
-> ConcurrencyState
-> state
-> (Maybe ThreadId, state)
scheduleThread Scheduler s
sched Maybe (ThreadId, ThreadAction)
p NonEmpty (ThreadId, Lookahead)
threads ConcurrencyState
cs s
s
newsched Maybe (ThreadId, ThreadAction)
Nothing NonEmpty (ThreadId, Lookahead)
threads ConcurrencyState
cs s
s = forall state.
Scheduler state
-> Maybe (ThreadId, ThreadAction)
-> NonEmpty (ThreadId, Lookahead)
-> ConcurrencyState
-> state
-> (Maybe ThreadId, state)
scheduleThread Scheduler s
sched forall a. Maybe a
Nothing NonEmpty (ThreadId, Lookahead)
threads ConcurrencyState
cs s
s