@@ -53,7 +53,9 @@ module Control.Monad.IOSim.Internal
53
53
54
54
import Prelude hiding (read )
55
55
56
- import Data.Foldable (traverse_ )
56
+ import Deque.Strict (Deque )
57
+ import qualified Deque.Strict as Deque
58
+ import Data.Foldable (traverse_ , toList )
57
59
import qualified Data.List as List
58
60
import qualified Data.List.Trace as Trace
59
61
import Data.Maybe (mapMaybe )
@@ -66,6 +68,8 @@ import qualified Data.Set as Set
66
68
import Data.Time (UTCTime (.. ), fromGregorian )
67
69
import Data.Dynamic
68
70
71
+ import GHC.Exts (fromList )
72
+
69
73
import Control.Exception (NonTermination (.. ),
70
74
assert , throw )
71
75
import Control.Monad (join )
@@ -123,7 +127,7 @@ data TimerVars s = TimerVars !(TVar s TimeoutState) !(TVar s Bool)
123
127
-- | Internal state.
124
128
--
125
129
data SimState s a = SimState {
126
- runqueue :: ! [ ThreadId ] ,
130
+ runqueue :: ! ( Deque ThreadId ) ,
127
131
-- | All threads other than the currently running thread: both running
128
132
-- and blocked threads.
129
133
threads :: ! (Map ThreadId (Thread s a )),
@@ -140,7 +144,7 @@ data SimState s a = SimState {
140
144
initialState :: SimState s a
141
145
initialState =
142
146
SimState {
143
- runqueue = [] ,
147
+ runqueue = mempty ,
144
148
threads = Map. empty,
145
149
curTime = Time 0 ,
146
150
timers = PSQ. empty,
@@ -156,15 +160,15 @@ invariant :: Maybe (Thread s a) -> SimState s a -> Bool
156
160
invariant (Just running) simstate@ SimState {runqueue,threads,clocks} =
157
161
not (threadBlocked running)
158
162
&& threadId running `Map.notMember` threads
159
- && threadId running `List.notElem` runqueue
163
+ && threadId running `List.notElem` toList runqueue
160
164
&& threadClockId running `Map.member` clocks
161
165
&& invariant Nothing simstate
162
166
163
167
invariant Nothing SimState {runqueue,threads,clocks} =
164
168
all (`Map.member` threads) runqueue
165
169
&& and [ threadBlocked t == (threadId t `notElem` runqueue)
166
170
| t <- Map. elems threads ]
167
- && runqueue == List. nub runqueue
171
+ && toList runqueue == List. nub (toList runqueue)
168
172
&& and [ threadClockId t `Map.member` clocks
169
173
| t <- Map. elems threads ]
170
174
@@ -400,7 +404,7 @@ schedule thread@Thread{
400
404
, threadNextTId = 1
401
405
}
402
406
threads' = Map. insert tid' thread'' threads
403
- trace <- schedule thread' simstate { runqueue = runqueue ++ [ tid']
407
+ trace <- schedule thread' simstate { runqueue = Deque. snoc tid' runqueue
404
408
, threads = threads' }
405
409
return (SimTrace time tid tlbl (EventThreadForked tid') trace)
406
410
@@ -563,7 +567,7 @@ deschedule Yield thread simstate@SimState{runqueue, threads} =
563
567
-- algorithms are not sensitive to the exact policy, so long as it is a
564
568
-- fair policy (all runnable threads eventually run).
565
569
566
- let runqueue' = runqueue ++ [ threadId thread]
570
+ let runqueue' = Deque. snoc ( threadId thread) runqueue
567
571
threads' = Map. insert (threadId thread) thread threads in
568
572
reschedule simstate { runqueue = runqueue', threads = threads' }
569
573
@@ -629,7 +633,8 @@ deschedule Sleep _thread _simstate =
629
633
-- When there is no current running thread but the runqueue is non-empty then
630
634
-- schedule the next one to run.
631
635
reschedule :: SimState s a -> ST s (SimTrace a )
632
- reschedule simstate@ SimState { runqueue = tid: runqueue', threads } =
636
+ reschedule simstate@ SimState { runqueue, threads }
637
+ | Just (tid, runqueue') <- Deque. uncons runqueue =
633
638
assert (invariant Nothing simstate) $
634
639
635
640
let thread = threads Map. ! tid in
@@ -638,7 +643,7 @@ reschedule simstate@SimState{ runqueue = tid:runqueue', threads } =
638
643
639
644
-- But when there are no runnable threads, we advance the time to the next
640
645
-- timer event, or stop.
641
- reschedule simstate@ SimState { runqueue = [] , threads, timers, curTime = time } =
646
+ reschedule simstate@ SimState { threads, timers, curTime = time } =
642
647
assert (invariant Nothing simstate) $
643
648
644
649
-- important to get all events that expire at this time
@@ -679,7 +684,7 @@ unblockThreads wakeup simstate@SimState {runqueue, threads} =
679
684
-- To preserve our invariants (that threadBlocked is correct)
680
685
-- we update the runqueue and threads together here
681
686
(unblocked, simstate {
682
- runqueue = runqueue ++ unblocked,
687
+ runqueue = runqueue <> fromList unblocked,
683
688
threads = threads'
684
689
})
685
690
where
0 commit comments