packages feed

haskell-cnc-0.1.3.200: Intel/Cnc4.hs

{-# LANGUAGE FlexibleInstances
  , BangPatterns
  , MagicHash 
  , ScopedTypeVariables
  , TypeFamilies 
  , UndecidableInstances
  , OverlappingInstances
  , DeriveDataTypeable
  , MultiParamTypeClasses
  , NamedFieldPuns
  #-}
-- State monad transformer is needed for both step & graph:
#ifndef MODNAME
#define MODNAME Intel.Cnc4
#endif
#define CNC_SCHEDULER 4
#define STEPLIFT  S.lift$
#define GRAPHLIFT S.lift$
#define SUPPRESS_runGraph
#define DEFINED_free_items
#include "Cnc.Header.hs"

------------------------------------------------------------
-- Version 4: Global work queue and worker threads that spin until
-- execution is finished.  Note, this ALSO includes the mortal threads
-- business from version 6.

#include "shared_5_6.hs"


-- FIXME: TODO: This version needs the Mortal threads mechanism in version 6...
-- Otherwise it creates extra threads that SPIN, which is terrible.

----------------------------------------------------------------------------------------------------
 
get col tag = ver5_6_core_get (return ()) col tag

-- get col tag = 
--  do (HiddenState5 { stack, mortal }) <- S.get
--     let io = do myId  <- myThreadId	      
--  	        modifyHotVar_ mortal (Set.insert myId)
--     ver5_6_core_get io col tag


-- At finalize time we set up the workers and run them.
finalize userFinalAction = 
    do (state @ HiddenState5 { stack, numworkers, mortal } ) <- S.get
       
       let worker id = 
	       do x <- STEPLIFT tryPop stack
                  let lifecheck = 
		        do myId <- STEPLIFT myThreadId
			   set  <- STEPLIFT readHotVar mortal
			   return (Set.notMember myId set)
		  case x of 
		    Nothing -> do n <- STEPLIFT readHotVar numworkers
				  --STEPLIFT putStrLn$ "NUM WORKERS IS " ++ show n++"\n"
				  -- numWorkers == 0 implies a message to shutdown.
				  if n == 0 
				   then do --STEPLIFT putStrLn$ "================ SHUTTING DOWN "++ show id ++"=============="
					   return ()					
				   else do -- A mortal thread should never spin:
					   b <- lifecheck
					   if b 
					    -- Should we be cooperative by sleeping a little?
					    --System.Posix.usleep 1000
					    then do STEPLIFT yield
						    worker id
					    else return ()
		    Just action -> do action
				      b <- lifecheck
				      if b then worker id else return ()

       let finalAction = 
	    do S.modify$ \stt -> stt { myid = numCapabilities-1 }

               val <- userFinalAction
	       -- UGLY Convention: reusing numworkers variable that's already in the type:
	       -- This variable becomes a "command" rather than diagnosing the current state.  Zero means stop working.
	       STEPLIFT writeHotVar numworkers 0 -- Shut workers down (eventually).
	       --STEPLIFT putStrLn$ " ..............>>>>>>>>>>>>>>>>>>> Initiated shutdown...........\n"
	       return val

       -- The final action will itself be one of the threads and it
       -- will replace itself when it blocks on a get.  Therefore we
       -- request one fewer worker:
       --ver5_6_core_finalize joiner finalAction worker False (numCapabilities-1)
       -- 
       -- FIXME: TODO: Currently having inexplicable problems on embarassingly_par with the N-1 approach.
       -- For now oversubscribing intentionally as the lesser of evils:
       ver5_6_core_finalize (error "joiner unused") finalAction worker False numCapabilities (\_ -> return ())

------------------------------------------------------------

quiescence_support = False