{-# LANGUAGE FlexibleInstances , BangPatterns , MagicHash , ScopedTypeVariables , DeriveDataTypeable , MultiParamTypeClasses #-} -- State monad transformer is needed for both step & graph: #ifndef MODNAME #define MODNAME Intel.Cnc6 #endif #define CNC_SCHEDULER 6 #define STEPLIFT S.lift$ #define GRAPHLIFT S.lift$ #define SUPPRESS_runGraph #include "Cnc.Header.hs" ------------------------------------------------------------ -- Version 6: Blocking with replacement. #include "shared_5_6.hs" -- When a thread goes down (blocks waiting on data) this version -- regenerates a new thread to replace it. The thread that went down -- is mortal when it wakes up. It will finish what it was doing and -- then die. -- This version is correct but sometimes inefficient. It can have -- threads terminate prematurely when the program enters a serial -- bottleneck. -- Then at finalize time we set up the workers and run them. finalize finalAction = do joiner <- GRAPHLIFT newChan let worker :: StepCode () = do x <- STEPLIFT tryPop global_stack case x of Nothing -> STEPLIFT writeChan joiner () Just action -> do action myId <- STEPLIFT myThreadId set <- STEPLIFT readIORef global_mortalthreads if Set.notMember myId set then worker -- keep going else STEPLIFT writeChan joiner () ver5_6_core_finalize joiner finalAction worker get col tag = ver5_6_core_get io col tag where io = do myId <- myThreadId atomicModifyIORef global_mortalthreads (\s -> (Set.insert myId s, ())) quiescence_support = True ------------------------------------------------------------ -- Version 7: Now with healing -- bring back worker threads that died -- prematurely. -- TODO: Improve on 6 by correcting premature deaths.