{-# LANGUAGE ExistentialQuantification #-}
module Transient.Mailboxes where
import Transient.Internals
import Transient.EVars
import qualified Data.Map as M
import Data.IORef
import Data.Typeable
import System.IO.Unsafe
import Unsafe.Coerce
import Control.Monad.IO.Class
mailboxes :: IORef (M.Map MailboxId (EVar SData))
mailboxes= unsafePerformIO $ newIORef M.empty
data MailboxId = forall a .(Typeable a, Ord a) => MailboxId a TypeRep
instance Eq MailboxId where
id1 == id2 = id1 `compare` id2== EQ
instance Ord MailboxId where
MailboxId n t `compare` MailboxId n' t'=
case typeOf n `compare` typeOf n' of
EQ -> case n `compare` unsafeCoerce n' of
EQ -> t `compare` t'
LT -> LT
GT -> GT
other -> other
instance Show MailboxId where
show ( MailboxId _ t) = show t
putMailbox :: Typeable val => val -> TransIO ()
putMailbox = putMailbox' (0::Int)
putMailbox' :: (Typeable key, Ord key, Typeable val) => key -> val -> TransIO ()
putMailbox' idbox dat= do
let name= MailboxId idbox $ typeOf dat
mbs <- liftIO $ readIORef mailboxes
let mev = M.lookup name mbs
case mev of
Nothing -> newMailbox name >> putMailbox' idbox dat
Just ev -> writeEVar ev $ unsafeCoerce dat
newMailbox :: MailboxId -> TransIO ()
newMailbox name= do
ev <- newEVar
liftIO $ atomicModifyIORef mailboxes $ \mv -> (M.insert name ev mv,())
getMailbox :: Typeable val => TransIO val
getMailbox = getMailbox' (0 :: Int)
getMailbox' :: (Typeable key, Ord key, Typeable val) => key -> TransIO val
getMailbox' mboxid = x where
x = do
let name= MailboxId mboxid $ typeOf $ typeOfM x
mbs <- liftIO $ readIORef mailboxes
let mev = M.lookup name mbs
case mev of
Nothing ->newMailbox name >> getMailbox' mboxid
Just ev ->unsafeCoerce $ readEVar ev
typeOfM :: TransIO a -> a
typeOfM = undefined
deleteMailbox :: Typeable a => a -> TransIO ()
deleteMailbox = deleteMailbox' (0 ::Int)
deleteMailbox' :: (Typeable key, Ord key, Typeable a) => key -> a -> TransIO ()
deleteMailbox' mboxid witness= do
let name= MailboxId mboxid $ typeOf witness
mbs <- liftIO $ readIORef mailboxes
let mev = M.lookup name mbs
case mev of
Nothing -> return()
Just ev -> do cleanEVar ev
liftIO $ atomicModifyIORef mailboxes $ \bs -> (M.delete name bs,())