module Control.Parallel.HdpH.Internal.Misc
(
AnyType(..),
Forkable(
fork,
forkOn
),
Cont(..),
rotate,
decode,
decodeLazy,
encode,
encodeLazy,
encodeBytes,
decodeBytes,
fromLeft,
fromRight,
splitAtFirst,
rmElems,
Action,
ActionServer,
newServer,
killServer,
reqAction,
timeIO
) where
import Prelude hiding (error)
import Control.Concurrent (ThreadId, forkIO, killThread)
import Control.Concurrent.Chan (Chan, newChan, writeChan, readChan)
import Control.DeepSeq (NFData(rnf))
import Control.Monad (join)
import Control.Monad.Reader (ReaderT, runReaderT, ask)
import Control.Monad.Trans (lift)
import qualified Data.ByteString
as Strict (ByteString, foldl', unpack)
import qualified Data.ByteString.Lazy
as Lazy (ByteString, foldl', pack, unpack)
import Data.Serialize (Serialize)
import qualified Data.Serialize (encode, decode, encodeLazy, decodeLazy)
import Data.Time.Clock (NominalDiffTime, diffUTCTime, getCurrentTime)
import Data.Word (Word8)
import qualified GHC.Conc (forkOn)
import Control.Parallel.HdpH.Internal.Location (error)
rotate :: Int -> [a] -> [a]
rotate _ [] = []
rotate n xs = zipWith const (drop n $ cycle xs) xs
encode :: Serialize a => a -> Strict.ByteString
encode = Data.Serialize.encode
decode :: Serialize a => Strict.ByteString -> a
decode bs =
case Data.Serialize.decode bs of
Right x -> x
Left msg -> error $ "HdpH.Internal.Misc.decode " ++
showPrefix 10 bs ++ ": " ++ msg
encodeLazy :: Serialize a => a -> Lazy.ByteString
encodeLazy = Data.Serialize.encodeLazy
decodeLazy :: Serialize a => Lazy.ByteString -> a
decodeLazy bs =
case Data.Serialize.decodeLazy bs of
Right x -> x
Left msg -> error $ "HdpH.Internal.Misc.decodeLazy " ++
showPrefixLazy 10 bs ++ ": " ++ msg
decodeBytes :: Serialize a => [Word8] -> a
decodeBytes = decodeLazy . Lazy.pack
encodeBytes :: Serialize a => a -> [Word8]
encodeBytes = Lazy.unpack . Data.Serialize.encodeLazy
showPrefix :: Int -> Strict.ByteString -> String
showPrefix n bs = showListUpto n (Strict.unpack bs) ""
showPrefixLazy :: Int -> Lazy.ByteString -> String
showPrefixLazy n bs = showListUpto n (Lazy.unpack bs) ""
showListUpto :: (Show a) => Int -> [a] -> String -> String
showListUpto n [] = showString "[]"
showListUpto n (x:xs) = showString "[" . shows x . go (n 1) xs
where
go _ [] = showString "]"
go n (x:xs) | n > 0 = showString "," . shows x . go (n 1) xs
| otherwise = showString ",...]"
data AnyType :: * where
Any :: a -> AnyType
splitAtFirst :: (a -> Bool) -> [a] -> Maybe ([a], a, [a])
splitAtFirst p xs = let (left, rest) = break p xs in
case rest of
[] -> Nothing
middle:right -> Just (left, middle, right)
fromLeft :: Either a b -> a
fromLeft (Left x) = x
fromLeft _ = error "HdpH.Internal.Misc.fromLeft: wrong constructor"
fromRight :: Either a b -> b
fromRight (Right y) = y
fromRight _ = error "HdpH.Internal.Misc.fromRight: wrong constructor"
rmElems' :: Eq a => a -> [a] -> [a]
rmElems' deleted xs = [ x | x <- xs, x /= deleted ]
rmElems :: Eq a => [a] -> [a] -> [a]
rmElems [] xs = xs
rmElems [y] xs = rmElems' y xs
rmElems (y:ys) xs = rmElems ys (rmElems' y xs)
class (Monad m) => Forkable m where
fork :: m () -> m ThreadId
forkOn :: Int -> m () -> m ThreadId
instance Forkable IO where
fork = forkIO
forkOn = GHC.Conc.forkOn
instance (Forkable m) => Forkable (ReaderT i m) where
fork action = do state <- ask
lift $ fork $ runReaderT action state
forkOn cpu action = do state <- ask
lift $ forkOn cpu $ runReaderT action state
newtype Cont r a = Cont { runCont :: (a -> r) -> r }
instance Functor (Cont r) where
fmap f m = Cont $ \c -> runCont m (c . f)
instance Monad (Cont r) where
return a = Cont $ \ c -> c $! a
m >>= k = Cont $ \ c -> runCont m $ \ a -> runCont (k $! a) c
type Action = IO ()
data ActionServer = ActionServer (Chan Action) ThreadId
newServer :: IO ActionServer
newServer = do trigger <- newChan
tid <- forkIO $ server trigger
return (ActionServer trigger tid)
killServer :: ActionServer -> IO ()
killServer (ActionServer _ tid) = killThread tid
reqAction :: ActionServer -> Action -> IO ()
reqAction (ActionServer trigger _) = writeChan trigger
server :: Chan Action -> IO ()
server trigger = do join (readChan trigger)
server trigger
timeIO :: IO a -> IO (a, NominalDiffTime)
timeIO action = do t0 <- getCurrentTime
x <- action
t1 <- getCurrentTime
return (x, diffUTCTime t1 t0)