{- |
Copyright  : Will Thompson, Iñaki García Etxebarria and Jonas Platte
License    : LGPL-2.1
Maintainer : Iñaki García Etxebarria (inaki@blueleaf.cc)

This object provides an abstraction for creating threads. The default
implementation uses a regular GThreadPool to start tasks.

Subclasses can be made to create custom threads.
-}

#define ENABLE_OVERLOADING (MIN_VERSION_haskell_gi_overloading(1,0,0) \
       && !defined(__HADDOCK_VERSION__))

module GI.Gst.Objects.TaskPool
    (

-- * Exported types
    TaskPool(..)                            ,
    IsTaskPool                              ,
    toTaskPool                              ,
    noTaskPool                              ,


 -- * Methods
-- ** cleanup #method:cleanup#

#if ENABLE_OVERLOADING
    TaskPoolCleanupMethodInfo               ,
#endif
    taskPoolCleanup                         ,


-- ** join #method:join#

#if ENABLE_OVERLOADING
    TaskPoolJoinMethodInfo                  ,
#endif
    taskPoolJoin                            ,


-- ** new #method:new#

    taskPoolNew                             ,


-- ** prepare #method:prepare#

#if ENABLE_OVERLOADING
    TaskPoolPrepareMethodInfo               ,
#endif
    taskPoolPrepare                         ,


-- ** push #method:push#

#if ENABLE_OVERLOADING
    TaskPoolPushMethodInfo                  ,
#endif
    taskPoolPush                            ,




    ) where

import Data.GI.Base.ShortPrelude
import qualified Data.GI.Base.ShortPrelude as SP
import qualified Data.GI.Base.Overloading as O
import qualified Prelude as P

import qualified Data.GI.Base.Attributes as GI.Attributes
import qualified Data.GI.Base.ManagedPtr as B.ManagedPtr
import qualified Data.GI.Base.GClosure as B.GClosure
import qualified Data.GI.Base.GError as B.GError
import qualified Data.GI.Base.GVariant as B.GVariant
import qualified Data.GI.Base.GValue as B.GValue
import qualified Data.GI.Base.GParamSpec as B.GParamSpec
import qualified Data.GI.Base.CallStack as B.CallStack
import qualified Data.GI.Base.Properties as B.Properties
import qualified Data.Text as T
import qualified Data.ByteString.Char8 as B
import qualified Data.Map as Map
import qualified Foreign.Ptr as FP
import qualified GHC.OverloadedLabels as OL

import qualified GI.GObject.Objects.Object as GObject.Object
import qualified GI.Gst.Callbacks as Gst.Callbacks
import {-# SOURCE #-} qualified GI.Gst.Objects.Object as Gst.Object

-- | Memory-managed wrapper type.
newtype TaskPool = TaskPool (ManagedPtr TaskPool)
foreign import ccall "gst_task_pool_get_type"
    c_gst_task_pool_get_type :: IO GType

instance GObject TaskPool where
    gobjectType = c_gst_task_pool_get_type


-- | Type class for types which can be safely cast to `TaskPool`, for instance with `toTaskPool`.
class (GObject o, O.IsDescendantOf TaskPool o) => IsTaskPool o
instance (GObject o, O.IsDescendantOf TaskPool o) => IsTaskPool o

instance O.HasParentTypes TaskPool
type instance O.ParentTypes TaskPool = '[Gst.Object.Object, GObject.Object.Object]

-- | Cast to `TaskPool`, for types for which this is known to be safe. For general casts, use `Data.GI.Base.ManagedPtr.castTo`.
toTaskPool :: (MonadIO m, IsTaskPool o) => o -> m TaskPool
toTaskPool = liftIO . unsafeCastTo TaskPool

-- | A convenience alias for `Nothing` :: `Maybe` `TaskPool`.
noTaskPool :: Maybe TaskPool
noTaskPool = Nothing

#if ENABLE_OVERLOADING
type family ResolveTaskPoolMethod (t :: Symbol) (o :: *) :: * where
    ResolveTaskPoolMethod "addControlBinding" o = Gst.Object.ObjectAddControlBindingMethodInfo
    ResolveTaskPoolMethod "bindProperty" o = GObject.Object.ObjectBindPropertyMethodInfo
    ResolveTaskPoolMethod "bindPropertyFull" o = GObject.Object.ObjectBindPropertyFullMethodInfo
    ResolveTaskPoolMethod "cleanup" o = TaskPoolCleanupMethodInfo
    ResolveTaskPoolMethod "defaultError" o = Gst.Object.ObjectDefaultErrorMethodInfo
    ResolveTaskPoolMethod "forceFloating" o = GObject.Object.ObjectForceFloatingMethodInfo
    ResolveTaskPoolMethod "freezeNotify" o = GObject.Object.ObjectFreezeNotifyMethodInfo
    ResolveTaskPoolMethod "getv" o = GObject.Object.ObjectGetvMethodInfo
    ResolveTaskPoolMethod "hasActiveControlBindings" o = Gst.Object.ObjectHasActiveControlBindingsMethodInfo
    ResolveTaskPoolMethod "hasAncestor" o = Gst.Object.ObjectHasAncestorMethodInfo
    ResolveTaskPoolMethod "hasAsAncestor" o = Gst.Object.ObjectHasAsAncestorMethodInfo
    ResolveTaskPoolMethod "hasAsParent" o = Gst.Object.ObjectHasAsParentMethodInfo
    ResolveTaskPoolMethod "isFloating" o = GObject.Object.ObjectIsFloatingMethodInfo
    ResolveTaskPoolMethod "join" o = TaskPoolJoinMethodInfo
    ResolveTaskPoolMethod "notify" o = GObject.Object.ObjectNotifyMethodInfo
    ResolveTaskPoolMethod "notifyByPspec" o = GObject.Object.ObjectNotifyByPspecMethodInfo
    ResolveTaskPoolMethod "prepare" o = TaskPoolPrepareMethodInfo
    ResolveTaskPoolMethod "push" o = TaskPoolPushMethodInfo
    ResolveTaskPoolMethod "ref" o = Gst.Object.ObjectRefMethodInfo
    ResolveTaskPoolMethod "refSink" o = GObject.Object.ObjectRefSinkMethodInfo
    ResolveTaskPoolMethod "removeControlBinding" o = Gst.Object.ObjectRemoveControlBindingMethodInfo
    ResolveTaskPoolMethod "runDispose" o = GObject.Object.ObjectRunDisposeMethodInfo
    ResolveTaskPoolMethod "stealData" o = GObject.Object.ObjectStealDataMethodInfo
    ResolveTaskPoolMethod "stealQdata" o = GObject.Object.ObjectStealQdataMethodInfo
    ResolveTaskPoolMethod "suggestNextSync" o = Gst.Object.ObjectSuggestNextSyncMethodInfo
    ResolveTaskPoolMethod "syncValues" o = Gst.Object.ObjectSyncValuesMethodInfo
    ResolveTaskPoolMethod "thawNotify" o = GObject.Object.ObjectThawNotifyMethodInfo
    ResolveTaskPoolMethod "unparent" o = Gst.Object.ObjectUnparentMethodInfo
    ResolveTaskPoolMethod "unref" o = Gst.Object.ObjectUnrefMethodInfo
    ResolveTaskPoolMethod "watchClosure" o = GObject.Object.ObjectWatchClosureMethodInfo
    ResolveTaskPoolMethod "getControlBinding" o = Gst.Object.ObjectGetControlBindingMethodInfo
    ResolveTaskPoolMethod "getControlRate" o = Gst.Object.ObjectGetControlRateMethodInfo
    ResolveTaskPoolMethod "getData" o = GObject.Object.ObjectGetDataMethodInfo
    ResolveTaskPoolMethod "getGValueArray" o = Gst.Object.ObjectGetGValueArrayMethodInfo
    ResolveTaskPoolMethod "getName" o = Gst.Object.ObjectGetNameMethodInfo
    ResolveTaskPoolMethod "getParent" o = Gst.Object.ObjectGetParentMethodInfo
    ResolveTaskPoolMethod "getPathString" o = Gst.Object.ObjectGetPathStringMethodInfo
    ResolveTaskPoolMethod "getProperty" o = GObject.Object.ObjectGetPropertyMethodInfo
    ResolveTaskPoolMethod "getQdata" o = GObject.Object.ObjectGetQdataMethodInfo
    ResolveTaskPoolMethod "getValue" o = Gst.Object.ObjectGetValueMethodInfo
    ResolveTaskPoolMethod "setControlBindingDisabled" o = Gst.Object.ObjectSetControlBindingDisabledMethodInfo
    ResolveTaskPoolMethod "setControlBindingsDisabled" o = Gst.Object.ObjectSetControlBindingsDisabledMethodInfo
    ResolveTaskPoolMethod "setControlRate" o = Gst.Object.ObjectSetControlRateMethodInfo
    ResolveTaskPoolMethod "setData" o = GObject.Object.ObjectSetDataMethodInfo
    ResolveTaskPoolMethod "setName" o = Gst.Object.ObjectSetNameMethodInfo
    ResolveTaskPoolMethod "setParent" o = Gst.Object.ObjectSetParentMethodInfo
    ResolveTaskPoolMethod "setProperty" o = GObject.Object.ObjectSetPropertyMethodInfo
    ResolveTaskPoolMethod l o = O.MethodResolutionFailed l o

instance (info ~ ResolveTaskPoolMethod t TaskPool, O.MethodInfo info TaskPool p) => OL.IsLabel t (TaskPool -> p) where
#if MIN_VERSION_base(4,10,0)
    fromLabel = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info)
#else
    fromLabel _ = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info)
#endif

#endif

#if ENABLE_OVERLOADING
instance O.HasAttributeList TaskPool
type instance O.AttributeList TaskPool = TaskPoolAttributeList
type TaskPoolAttributeList = ('[ '("name", Gst.Object.ObjectNamePropertyInfo), '("parent", Gst.Object.ObjectParentPropertyInfo)] :: [(Symbol, *)])
#endif

#if ENABLE_OVERLOADING
#endif

#if ENABLE_OVERLOADING
type instance O.SignalList TaskPool = TaskPoolSignalList
type TaskPoolSignalList = ('[ '("deepNotify", Gst.Object.ObjectDeepNotifySignalInfo), '("notify", GObject.Object.ObjectNotifySignalInfo)] :: [(Symbol, *)])

#endif

-- method TaskPool::new
-- method type : Constructor
-- Args : []
-- Lengths : []
-- returnType : Just (TInterface (Name {namespace = "Gst", name = "TaskPool"}))
-- throws : False
-- Skip return : False

foreign import ccall "gst_task_pool_new" gst_task_pool_new ::
    IO (Ptr TaskPool)

{- |
Create a new default task pool. The default task pool will use a regular
GThreadPool for threads.
-}
taskPoolNew ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    m TaskPool
    {- ^ __Returns:__ a new 'GI.Gst.Objects.TaskPool.TaskPool'. 'GI.Gst.Objects.Object.objectUnref' after usage. -}
taskPoolNew  = liftIO $ do
    result <- gst_task_pool_new
    checkUnexpectedReturnNULL "taskPoolNew" result
    result' <- (wrapObject TaskPool) result
    return result'

#if ENABLE_OVERLOADING
#endif

-- method TaskPool::cleanup
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "pool", argType = TInterface (Name {namespace = "Gst", name = "TaskPool"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GstTaskPool", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Nothing
-- throws : False
-- Skip return : False

foreign import ccall "gst_task_pool_cleanup" gst_task_pool_cleanup ::
    Ptr TaskPool ->                         -- pool : TInterface (Name {namespace = "Gst", name = "TaskPool"})
    IO ()

{- |
Wait for all tasks to be stopped. This is mainly used internally
to ensure proper cleanup of internal data structures in test suites.

MT safe.
-}
taskPoolCleanup ::
    (B.CallStack.HasCallStack, MonadIO m, IsTaskPool a) =>
    a
    {- ^ /@pool@/: a 'GI.Gst.Objects.TaskPool.TaskPool' -}
    -> m ()
taskPoolCleanup pool = liftIO $ do
    pool' <- unsafeManagedPtrCastPtr pool
    gst_task_pool_cleanup pool'
    touchManagedPtr pool
    return ()

#if ENABLE_OVERLOADING
data TaskPoolCleanupMethodInfo
instance (signature ~ (m ()), MonadIO m, IsTaskPool a) => O.MethodInfo TaskPoolCleanupMethodInfo a signature where
    overloadedMethod _ = taskPoolCleanup

#endif

-- method TaskPool::join
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "pool", argType = TInterface (Name {namespace = "Gst", name = "TaskPool"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GstTaskPool", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "id", argType = TBasicType TPtr, direction = DirectionIn, mayBeNull = True, argDoc = Documentation {rawDocText = Just "the id", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Nothing
-- throws : False
-- Skip return : False

foreign import ccall "gst_task_pool_join" gst_task_pool_join ::
    Ptr TaskPool ->                         -- pool : TInterface (Name {namespace = "Gst", name = "TaskPool"})
    Ptr () ->                               -- id : TBasicType TPtr
    IO ()

{- |
Join a task and\/or return it to the pool. /@id@/ is the id obtained from
'GI.Gst.Objects.TaskPool.taskPoolPush'.
-}
taskPoolJoin ::
    (B.CallStack.HasCallStack, MonadIO m, IsTaskPool a) =>
    a
    {- ^ /@pool@/: a 'GI.Gst.Objects.TaskPool.TaskPool' -}
    -> Ptr ()
    {- ^ /@id@/: the id -}
    -> m ()
taskPoolJoin pool id = liftIO $ do
    pool' <- unsafeManagedPtrCastPtr pool
    gst_task_pool_join pool' id
    touchManagedPtr pool
    return ()

#if ENABLE_OVERLOADING
data TaskPoolJoinMethodInfo
instance (signature ~ (Ptr () -> m ()), MonadIO m, IsTaskPool a) => O.MethodInfo TaskPoolJoinMethodInfo a signature where
    overloadedMethod _ = taskPoolJoin

#endif

-- method TaskPool::prepare
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "pool", argType = TInterface (Name {namespace = "Gst", name = "TaskPool"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GstTaskPool", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Nothing
-- throws : True
-- Skip return : False

foreign import ccall "gst_task_pool_prepare" gst_task_pool_prepare ::
    Ptr TaskPool ->                         -- pool : TInterface (Name {namespace = "Gst", name = "TaskPool"})
    Ptr (Ptr GError) ->                     -- error
    IO ()

{- |
Prepare the taskpool for accepting 'GI.Gst.Objects.TaskPool.taskPoolPush' operations.

MT safe.
-}
taskPoolPrepare ::
    (B.CallStack.HasCallStack, MonadIO m, IsTaskPool a) =>
    a
    {- ^ /@pool@/: a 'GI.Gst.Objects.TaskPool.TaskPool' -}
    -> m ()
    {- ^ /(Can throw 'Data.GI.Base.GError.GError')/ -}
taskPoolPrepare pool = liftIO $ do
    pool' <- unsafeManagedPtrCastPtr pool
    onException (do
        propagateGError $ gst_task_pool_prepare pool'
        touchManagedPtr pool
        return ()
     ) (do
        return ()
     )

#if ENABLE_OVERLOADING
data TaskPoolPrepareMethodInfo
instance (signature ~ (m ()), MonadIO m, IsTaskPool a) => O.MethodInfo TaskPoolPrepareMethodInfo a signature where
    overloadedMethod _ = taskPoolPrepare

#endif

-- method TaskPool::push
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "pool", argType = TInterface (Name {namespace = "Gst", name = "TaskPool"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GstTaskPool", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "func", argType = TInterface (Name {namespace = "Gst", name = "TaskPoolFunction"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "the function to call", sinceVersion = Nothing}, argScope = ScopeTypeAsync, argClosure = 2, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "user_data", argType = TBasicType TPtr, direction = DirectionIn, mayBeNull = True, argDoc = Documentation {rawDocText = Just "data to pass to @func", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TBasicType TPtr)
-- throws : True
-- Skip return : False

foreign import ccall "gst_task_pool_push" gst_task_pool_push ::
    Ptr TaskPool ->                         -- pool : TInterface (Name {namespace = "Gst", name = "TaskPool"})
    FunPtr Gst.Callbacks.C_TaskPoolFunction -> -- func : TInterface (Name {namespace = "Gst", name = "TaskPoolFunction"})
    Ptr () ->                               -- user_data : TBasicType TPtr
    Ptr (Ptr GError) ->                     -- error
    IO (Ptr ())

{- |
Start the execution of a new thread from /@pool@/.
-}
taskPoolPush ::
    (B.CallStack.HasCallStack, MonadIO m, IsTaskPool a) =>
    a
    {- ^ /@pool@/: a 'GI.Gst.Objects.TaskPool.TaskPool' -}
    -> Gst.Callbacks.TaskPoolFunction
    {- ^ /@func@/: the function to call -}
    -> m (Ptr ())
    {- ^ __Returns:__ a pointer that should be used
for the gst_task_pool_join function. This pointer can be 'Nothing', you
must check /@error@/ to detect errors. /(Can throw 'Data.GI.Base.GError.GError')/ -}
taskPoolPush pool func = liftIO $ do
    pool' <- unsafeManagedPtrCastPtr pool
    ptrfunc <- callocMem :: IO (Ptr (FunPtr Gst.Callbacks.C_TaskPoolFunction))
    func' <- Gst.Callbacks.mk_TaskPoolFunction (Gst.Callbacks.wrap_TaskPoolFunction (Just ptrfunc) (Gst.Callbacks.drop_closures_TaskPoolFunction func))
    poke ptrfunc func'
    let userData = nullPtr
    onException (do
        result <- propagateGError $ gst_task_pool_push pool' func' userData
        touchManagedPtr pool
        return result
     ) (do
        return ()
     )

#if ENABLE_OVERLOADING
data TaskPoolPushMethodInfo
instance (signature ~ (Gst.Callbacks.TaskPoolFunction -> m (Ptr ())), MonadIO m, IsTaskPool a) => O.MethodInfo TaskPoolPushMethodInfo a signature where
    overloadedMethod _ = taskPoolPush

#endif