{-# LANGUAGE ScopedTypeVariables #-}
module Control.Concurrent.CFuture
(Future, CFuturePtr,
forkFuture, writeFutureC, forkFutureC,
get, getC, waitC, abort)
where
import Foreign.Ptr
import Foreign.StablePtr
import Foreign.Storable
import Control.Concurrent
import BasePrelude (PrimMVar, newStablePtrPrimMVar,
Int8, Int16, Int32, Int64,
Word8, Word16, Word32, Word64)
type CFuturePtr = Ptr (StablePtr PrimMVar)
data Future a = MkFuture
(MVar ())
(MVar (Maybe a))
forkFuture :: IO a -> IO (Future a)
forkFuture :: forall a. IO a -> IO (Future a)
forkFuture IO a
action = do
MVar ()
intMVar <- (IO (MVar ())
forall a. IO (MVar a)
newEmptyMVar :: IO (MVar ()))
MVar (Maybe a)
resMVar <- (IO (MVar (Maybe a))
forall a. IO (MVar a)
forall {a}. IO (MVar (Maybe a))
newEmptyMVar :: IO (MVar (Maybe a)))
ThreadId
calculationThreadId <- IO () -> IO ThreadId
forkIO (IO () -> IO ThreadId) -> IO () -> IO ThreadId
forall a b. (a -> b) -> a -> b
$ (MVar (Maybe a) -> Maybe a -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar (Maybe a)
resMVar (Maybe a -> IO ()) -> (a -> Maybe a) -> a -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Maybe a
forall a. a -> Maybe a
Just (a -> IO ()) -> IO a -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO a
action) IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> MVar () -> () -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar ()
intMVar ()
ThreadId
_ <- IO () -> IO ThreadId
forkIO (IO () -> IO ThreadId) -> IO () -> IO ThreadId
forall a b. (a -> b) -> a -> b
$ do
MVar () -> IO ()
forall a. MVar a -> IO a
readMVar MVar ()
intMVar
ThreadId -> IO ()
killThread ThreadId
calculationThreadId
MVar (Maybe a) -> Maybe a -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar (Maybe a)
resMVar Maybe a
forall a. Maybe a
Nothing
Future a -> IO (Future a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Future a -> IO (Future a)) -> Future a -> IO (Future a)
forall a b. (a -> b) -> a -> b
$ MVar () -> MVar (Maybe a) -> Future a
forall a. MVar () -> MVar (Maybe a) -> Future a
MkFuture MVar ()
intMVar MVar (Maybe a)
resMVar
abort :: Future a -> IO Bool
abort :: forall a. Future a -> IO Bool
abort (MkFuture MVar ()
intMVar MVar (Maybe a)
_) = MVar () -> () -> IO Bool
forall a. MVar a -> a -> IO Bool
tryPutMVar MVar ()
intMVar ()
writeFutureC :: CFuturePtr -> Future a -> IO ()
writeFutureC :: forall a. CFuturePtr -> Future a -> IO ()
writeFutureC CFuturePtr
ptr (MkFuture MVar ()
intMVar MVar (Maybe a)
resMVar) = do
StablePtr PrimMVar
intMVarSPtr <- MVar () -> IO (StablePtr PrimMVar)
forall a. MVar a -> IO (StablePtr PrimMVar)
newStablePtrPrimMVar MVar ()
intMVar
StablePtr (MVar (Maybe a))
resMVarSPtr <- MVar (Maybe a) -> IO (StablePtr (MVar (Maybe a)))
forall a. a -> IO (StablePtr a)
newStablePtr MVar (Maybe a)
resMVar
let convPtr :: CFuturePtr
convPtr = (CFuturePtr -> CFuturePtr
forall a b. Ptr a -> Ptr b
castPtr CFuturePtr
ptr :: CFuturePtr)
CFuturePtr -> StablePtr PrimMVar -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke CFuturePtr
convPtr StablePtr PrimMVar
intMVarSPtr
Ptr (StablePtr (MVar (Maybe a)))
-> Int -> StablePtr (MVar (Maybe a)) -> IO ()
forall a. Storable a => Ptr a -> Int -> a -> IO ()
pokeElemOff (CFuturePtr -> Ptr (StablePtr (MVar (Maybe a)))
forall a b. Ptr a -> Ptr b
castPtr CFuturePtr
convPtr) Int
1 StablePtr (MVar (Maybe a))
resMVarSPtr
forkFutureC :: CFuturePtr -> IO a -> IO ()
forkFutureC :: forall a. CFuturePtr -> IO a -> IO ()
forkFutureC CFuturePtr
ptr IO a
action = CFuturePtr -> Future a -> IO ()
forall a. CFuturePtr -> Future a -> IO ()
writeFutureC CFuturePtr
ptr (Future a -> IO ()) -> IO (Future a) -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO a -> IO (Future a)
forall a. IO a -> IO (Future a)
forkFuture IO a
action
get :: Future a -> IO (Maybe a)
get :: forall a. Future a -> IO (Maybe a)
get (MkFuture MVar ()
_ MVar (Maybe a)
resMVar) = MVar (Maybe a) -> IO (Maybe a)
forall a. MVar a -> IO a
readMVar MVar (Maybe a)
resMVar
getCHelper :: CFuturePtr -> (a -> IO ()) -> IO Bool
getCHelper :: forall a. CFuturePtr -> (a -> IO ()) -> IO Bool
getCHelper CFuturePtr
futurePtr a -> IO ()
doOnCompletion = do
StablePtr (MVar (Maybe a))
resMVarSPtr <- Ptr (StablePtr (MVar (Maybe a)))
-> Int -> IO (StablePtr (MVar (Maybe a)))
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (CFuturePtr -> Ptr (StablePtr (MVar (Maybe a)))
forall a b. Ptr a -> Ptr b
castPtr CFuturePtr
futurePtr :: Ptr (StablePtr (MVar (Maybe a)))) Int
1
Maybe a
result <- MVar (Maybe a) -> IO (Maybe a)
forall a. MVar a -> IO a
readMVar (MVar (Maybe a) -> IO (Maybe a))
-> IO (MVar (Maybe a)) -> IO (Maybe a)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< StablePtr (MVar (Maybe a)) -> IO (MVar (Maybe a))
forall a. StablePtr a -> IO a
deRefStablePtr StablePtr (MVar (Maybe a))
resMVarSPtr
case Maybe a
result of
Just a
a -> a -> IO ()
doOnCompletion a
a IO () -> IO Bool -> IO Bool
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
Maybe a
_ -> Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
getC :: Storable a => CFuturePtr -> Ptr a -> IO Bool
getC :: forall a. Storable a => CFuturePtr -> Ptr a -> IO Bool
getC CFuturePtr
futurePtr Ptr a
destPtr = CFuturePtr -> (a -> IO ()) -> IO Bool
forall a. CFuturePtr -> (a -> IO ()) -> IO Bool
getCHelper CFuturePtr
futurePtr (Ptr a -> a -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr a
destPtr)
waitC :: CFuturePtr -> IO Bool
waitC :: CFuturePtr -> IO Bool
waitC CFuturePtr
futurePtr = CFuturePtr -> (Any -> IO ()) -> IO Bool
forall a. CFuturePtr -> (a -> IO ()) -> IO Bool
getCHelper CFuturePtr
futurePtr ((Any -> IO ()) -> IO Bool) -> (Any -> IO ()) -> IO Bool
forall a b. (a -> b) -> a -> b
$ IO () -> Any -> IO ()
forall a b. a -> b -> a
const (IO () -> Any -> IO ()) -> IO () -> Any -> IO ()
forall a b. (a -> b) -> a -> b
$ () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
foreign export ccall "getC_Char" getC :: CFuturePtr -> Ptr Char -> IO Bool
foreign export ccall "getC_Int" getC :: CFuturePtr -> Ptr Int -> IO Bool
foreign export ccall "getC_Int8" getC :: CFuturePtr -> Ptr Int8 -> IO Bool
foreign export ccall "getC_Int16" getC :: CFuturePtr -> Ptr Int16 -> IO Bool
foreign export ccall "getC_Int32" getC :: CFuturePtr -> Ptr Int32 -> IO Bool
foreign export ccall "getC_Int64" getC :: CFuturePtr -> Ptr Int64 -> IO Bool
foreign export ccall "getC_Word" getC :: CFuturePtr -> Ptr Word -> IO Bool
foreign export ccall "getC_Word8" getC :: CFuturePtr -> Ptr Word8 -> IO Bool
foreign export ccall "getC_Word16" getC :: CFuturePtr -> Ptr Word16 -> IO Bool
foreign export ccall "getC_Word32" getC :: CFuturePtr -> Ptr Word32 -> IO Bool
foreign export ccall "getC_Word64" getC :: CFuturePtr -> Ptr Word64 -> IO Bool
foreign export ccall "getC_Float" getC :: CFuturePtr -> Ptr Float -> IO Bool
foreign export ccall "getC_Double" getC :: CFuturePtr -> Ptr Double -> IO Bool
foreign export ccall "getC_Bool" getC :: CFuturePtr -> Ptr Bool -> IO Bool
foreign export ccall "getC_Ptr" getC :: CFuturePtr -> Ptr (Ptr a) -> IO Bool
foreign export ccall "getC_FunPtr" getC :: CFuturePtr -> Ptr (FunPtr a) -> IO Bool
foreign export ccall "getC_StablePtr" getC :: CFuturePtr -> Ptr (StablePtr a) -> IO Bool
foreign export ccall waitC :: CFuturePtr -> IO Bool