{-# OPTIONS_GHC -O2 -fno-full-laziness #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
-- Argh... for whatever reason this file cannot be compiled with optimization
-- -fno-full-laziness fixes this
-- Todo: check ghc-core to find out why
module SideChannelQ (Q(), enQ, deQ, runResultQueue) where
--import Control.Monad.Queue.Class
import Control.Monad.Cont.Class
import Data.IORef
import System.IO.Unsafe
import qualified Debug.Trace
-- trace = Debug.Trace.trace
-- traceIO = putStr
trace _ = id
traceIO _ = return ()
type QSt r' r = IORef r' -> IORef [r] -> Int -> [r] -> [r]
newtype Q r' r a = Q { unQ :: ((a -> QSt r' r) -> QSt r' r) }
instance Monad (Q r' r) where
return a = Q ($a)
m >>= f = Q (\k -> unQ m (\a -> unQ (f a) k))
instance MonadCont (Q r' r) where
callCC f = Q (\k -> unQ (f (\a -> Q (\_ -> k a))) k)
unsafeRead ref = unsafePerformIO (readIORef ref )
unsafeWrite ref a = unsafePerformIO (writeIORef ref a)
unsafeNew a = unsafePerformIO (newIORef a )
enQ x = Q (\k rr' rr !n xs -> let !n' = n+1
xs' = k () rr' rr n' xs
in trace ("enQ $ " ++ show x)
(unsafeWrite rr xs' `seq` (x:xs')))
deQ = Q delta
where
delta k rr' rr 0 xs = trace ("deQ failed") (k Nothing rr' rr 0 xs)
delta k rr' rr (n+1) (x:xs) = trace ("deQ " ++ show x) (k (Just x) rr' rr n xs)
breakK a rr' rr n xs = trace ("setting return value: " ++ show a)
(unsafeWrite rr' (\() -> a) `seq` [])
force [] = return ()
force (_:_) = return ()
demand [] = ()
demand (_:_) = ()
runResultQueue m
= (trace "reading return value" `seq` unsafeRead rr' (), queue)
where
rr' = unsafeNew init
init () = unsafePerformIO $ do
traceIO "forcing computation\n"
xs <- readIORef rr
force xs
traceIO "reading return value\n"
f <- readIORef rr'
return (f ())
rr = unsafeNew queue
queue = unQ m breakK rr' rr 0 queue