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

------------------------------------------------------------
-- Version 5a: A global work queue.
-- (This version has been disabled/removed.)
-- This version uses a global work-queue.
-- Here laziness comes in handy, we queue the thunks.

#include "shared_5_6.hs"

------------------------------------------------------------
-- Version 5: Thread spammer -- fork a permanent worker every time we block.

-- TODO: we should do a better job here by using a monad transformer on top of IO:
-- But if we must keep the same CnC interface... This is expedient:
 
get col tag = ver5_6_core_get (return ()) col tag

-- At finalize time we set up the workers and run them.
finalize finalAction = 
    do (HiddenState5 (stack, _, _, _)) <- S.get
       joiner <- GRAPHLIFT newChan 
       let worker = 
	       do x <- STEPLIFT tryPop stack
		  case x of 
		    Nothing -> STEPLIFT writeChan joiner ()
		    Just action -> do action
				      worker      
       ver5_6_core_finalize joiner finalAction worker 

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

quiescence_support = True

type Item = MVar
newItem  = STEPLIFT newEmptyMVar
readItem = grabWithBackup (return ())
putItem mv x = 
  do b <- STEPLIFT tryPutMVar mv x
     if b then return ()
	  else error "Violation of single assignment rule; second put on Item!"