{-# 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