synthesizer-llvm-0.8: src/Synthesizer/LLVM/ForeignPtr.hs
{-# LANGUAGE FlexibleContexts #-}
{- |
Adding the finalizer to a ForeignPtr seems to be the only way
that warrants execution of the finalizer (not too early and not never).
However, the normal ForeignPtr finalizers must be independent from Haskell runtime.
In contrast to ForeignPtr finalizers,
addFinalizer adds finalizers to boxes, that are optimized away.
Thus finalizers are run too early or not at all.
Concurrent.ForeignPtr and using threaded execution
is the only way to get finalizers in Haskell IO.
-}
module Synthesizer.LLVM.ForeignPtr where
import qualified LLVM.Extra.Memory as Memory
import LLVM.Extra.Class (MakeValueTuple, ValueTuple, )
import qualified LLVM.ExecutionEngine as EE
import qualified Foreign.Marshal.Utils as Marshal
import qualified Foreign.ForeignPtr as FPtr
import qualified Foreign.Concurrent as FC
import Foreign.ForeignPtr (ForeignPtr, withForeignPtr, )
import Foreign.StablePtr (newStablePtr, freeStablePtr)
import Foreign.Storable (Storable, poke, )
import Foreign.Ptr (Ptr, nullPtr, )
newAux :: IO () -> IO (ForeignPtr ())
newAux = FC.newForeignPtr nullPtr
makeFinalizer :: (EE.ExecutionEngine, IO ()) -> IO (IO ())
makeFinalizer (ee, finalizer) = do
stable <- newStablePtr ee
return $ finalizer >> freeStablePtr stable
newInit ::
(EE.ExecutionEngine, Ptr a -> IO ()) -> IO (Ptr a) -> IO (ForeignPtr a)
newInit (ee, stop) start = do
state <- start
FC.newForeignPtr state =<< makeFinalizer (ee, stop state)
newParam ::
(Storable b, MakeValueTuple b, Memory.C (ValueTuple b)) =>
(EE.ExecutionEngine, Ptr a -> IO ()) ->
(Ptr (Memory.Struct (ValueTuple b)) -> IO (Ptr a)) ->
b -> IO (ForeignPtr a)
newParam stop start b =
newInit stop (Marshal.with b (start . Memory.castStorablePtr))
new :: Storable a => IO () -> a -> IO (ForeignPtr a)
new finalizer a = do
ptr <- FPtr.mallocForeignPtr
FC.addForeignPtrFinalizer ptr finalizer
withForeignPtr ptr (flip poke a)
return ptr
with ::
(Storable a, MakeValueTuple a, Memory.C (ValueTuple a)) =>
ForeignPtr a -> (Ptr (Memory.Struct (ValueTuple a)) -> IO b) -> IO b
with fp func =
withForeignPtr fp (func . Memory.castStorablePtr)