-- Some helper functions to create closures.
module Data.GI.Base.Closure
    ( Closure(..)
    , newCClosure
    , noClosure
    ) where

import Foreign

import Data.GI.Base.BasicTypes
import Data.GI.Base.ManagedPtr (wrapBoxed)
import Data.GI.Base.Utils (safeFreeFunPtrPtr)

newtype Closure = Closure (ManagedPtr Closure)

noClosure :: Maybe Closure
noClosure :: Maybe Closure
noClosure = Maybe Closure
forall a. Maybe a
Nothing

foreign import ccall "g_closure_get_type" c_g_closure_get_type ::
    IO GType

instance BoxedObject Closure where
    boxedType :: Closure -> IO GType
boxedType _ = IO GType
c_g_closure_get_type


foreign import ccall "g_cclosure_new" g_cclosure_new
    :: FunPtr a -> Ptr () -> FunPtr c -> IO (Ptr Closure)

foreign import ccall "g_closure_ref" g_closure_ref
    :: Ptr Closure -> IO (Ptr Closure)

foreign import ccall "g_closure_sink" g_closure_sink
    :: Ptr Closure -> IO ()

newCClosure :: FunPtr a -> IO Closure
newCClosure :: FunPtr a -> IO Closure
newCClosure ptr :: FunPtr a
ptr = do
  Ptr Closure
closure <- FunPtr a -> Ptr () -> FunPtr (Ptr Any -> IO ()) -> IO (Ptr Closure)
forall a c. FunPtr a -> Ptr () -> FunPtr c -> IO (Ptr Closure)
g_cclosure_new FunPtr a
ptr Ptr ()
forall a. Ptr a
nullPtr FunPtr (Ptr Any -> IO ())
forall a. FunPtr (Ptr a -> IO ())
safeFreeFunPtrPtr
  -- The Haskell runtime will manage the memory associated to the
  -- closure, so ref and sink to let GLib know this.
  Ptr Closure -> IO (Ptr Closure)
g_closure_ref Ptr Closure
closure IO (Ptr Closure) -> (Ptr Closure -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Ptr Closure -> IO ()
g_closure_sink
  (ManagedPtr Closure -> Closure) -> Ptr Closure -> IO Closure
forall a.
(HasCallStack, BoxedObject a) =>
(ManagedPtr a -> a) -> Ptr a -> IO a
wrapBoxed ManagedPtr Closure -> Closure
Closure Ptr Closure
closure