{- | Copyright : Will Thompson, Iñaki García Etxebarria and Jonas Platte License : LGPL-2.1 Maintainer : Iñaki García Etxebarria (garetxe@gmail.com) Provides a base class for implementing asynchronous function results. Asynchronous operations are broken up into two separate operations which are chained together by a 'GI.Gio.Callbacks.AsyncReadyCallback'. To begin an asynchronous operation, provide a 'GI.Gio.Callbacks.AsyncReadyCallback' to the asynchronous function. This callback will be triggered when the operation has completed, and must be run in a later iteration of the [thread-default main context][g-main-context-push-thread-default] from where the operation was initiated. It will be passed a 'GI.Gio.Interfaces.AsyncResult.AsyncResult' instance filled with the details of the operation\'s success or failure, the object the asynchronous function was started for and any error codes returned. The asynchronous callback function is then expected to call the corresponding \"@/_finish()/@\" function, passing the object the function was called for, the 'GI.Gio.Interfaces.AsyncResult.AsyncResult' instance, and (optionally) an /@error@/ to grab any error conditions that may have occurred. The \"@/_finish()/@\" function for an operation takes the generic result (of type 'GI.Gio.Interfaces.AsyncResult.AsyncResult') and returns the specific result that the operation in question yields (e.g. a 'GI.Gio.Objects.FileEnumerator.FileEnumerator' for a \"enumerate children\" operation). If the result or error status of the operation is not needed, there is no need to call the \"@/_finish()/@\" function; GIO will take care of cleaning up the result and error information after the 'GI.Gio.Callbacks.AsyncReadyCallback' returns. You can pass 'Nothing' for the 'GI.Gio.Callbacks.AsyncReadyCallback' if you don\'t need to take any action at all after the operation completes. Applications may also take a reference to the 'GI.Gio.Interfaces.AsyncResult.AsyncResult' and call \"@/_finish()/@\" later; however, the \"@/_finish()/@\" function may be called at most once. Example of a typical asynchronous operation flow: === /C code/ > >void _theoretical_frobnitz_async (Theoretical *t, > GCancellable *c, > GAsyncReadyCallback cb, > gpointer u); > >gboolean _theoretical_frobnitz_finish (Theoretical *t, > GAsyncResult *res, > GError **e); > >static void >frobnitz_result_func (GObject *source_object, > GAsyncResult *res, > gpointer user_data) >{ > gboolean success = FALSE; > > success = _theoretical_frobnitz_finish (source_object, res, NULL); > > if (success) > g_printf ("Hurray!\n"); > else > g_printf ("Uh oh!\n"); > > ... > >} > >int main (int argc, void *argv[]) >{ > ... > > _theoretical_frobnitz_async (theoretical_data, > NULL, > frobnitz_result_func, > NULL); > > ... >} The callback for an asynchronous operation is called only once, and is always called, even in the case of a cancelled operation. On cancellation the result is a 'GI.Gio.Enums.IOErrorEnumCancelled' error. ## I\/O Priority # {@/io/@-priority} Many I\/O-related asynchronous operations have a priority parameter, which is used in certain cases to determine the order in which operations are executed. They are not used to determine system-wide I\/O scheduling. Priorities are integers, with lower numbers indicating higher priority. It is recommended to choose priorities between 'GI.GLib.Constants.PRIORITY_LOW' and 'GI.GLib.Constants.PRIORITY_HIGH', with 'GI.GLib.Constants.PRIORITY_DEFAULT' as a default. -} #define ENABLE_OVERLOADING (MIN_VERSION_haskell_gi_overloading(1,0,0) \ && !defined(__HADDOCK_VERSION__)) module GI.Gio.Interfaces.AsyncResult ( -- * Exported types AsyncResult(..) , noAsyncResult , IsAsyncResult , toAsyncResult , -- * Methods -- ** getSourceObject #method:getSourceObject# #if ENABLE_OVERLOADING AsyncResultGetSourceObjectMethodInfo , #endif asyncResultGetSourceObject , -- ** getUserData #method:getUserData# #if ENABLE_OVERLOADING AsyncResultGetUserDataMethodInfo , #endif asyncResultGetUserData , -- ** isTagged #method:isTagged# #if ENABLE_OVERLOADING AsyncResultIsTaggedMethodInfo , #endif asyncResultIsTagged , -- ** legacyPropagateError #method:legacyPropagateError# #if ENABLE_OVERLOADING AsyncResultLegacyPropagateErrorMethodInfo, #endif asyncResultLegacyPropagateError , ) 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.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.Text as T import qualified Data.ByteString.Char8 as B import qualified Data.Map as Map import qualified Foreign.Ptr as FP import qualified GI.GObject.Objects.Object as GObject.Object -- interface AsyncResult -- | Memory-managed wrapper type. newtype AsyncResult = AsyncResult (ManagedPtr AsyncResult) -- | A convenience alias for `Nothing` :: `Maybe` `AsyncResult`. noAsyncResult :: Maybe AsyncResult noAsyncResult = Nothing #if ENABLE_OVERLOADING type instance O.SignalList AsyncResult = AsyncResultSignalList type AsyncResultSignalList = ('[ '("notify", GObject.Object.ObjectNotifySignalInfo)] :: [(Symbol, *)]) #endif foreign import ccall "g_async_result_get_type" c_g_async_result_get_type :: IO GType instance GObject AsyncResult where gobjectType _ = c_g_async_result_get_type -- | Type class for types which can be safely cast to `AsyncResult`, for instance with `toAsyncResult`. class GObject o => IsAsyncResult o #if MIN_VERSION_base(4,9,0) instance {-# OVERLAPPABLE #-} (GObject a, O.UnknownAncestorError AsyncResult a) => IsAsyncResult a #endif instance IsAsyncResult AsyncResult instance GObject.Object.IsObject AsyncResult -- | Cast to `AsyncResult`, for types for which this is known to be safe. For general casts, use `Data.GI.Base.ManagedPtr.castTo`. toAsyncResult :: (MonadIO m, IsAsyncResult o) => o -> m AsyncResult toAsyncResult = liftIO . unsafeCastTo AsyncResult #if ENABLE_OVERLOADING instance O.HasAttributeList AsyncResult type instance O.AttributeList AsyncResult = AsyncResultAttributeList type AsyncResultAttributeList = ('[ ] :: [(Symbol, *)]) #endif #if ENABLE_OVERLOADING #endif #if ENABLE_OVERLOADING type family ResolveAsyncResultMethod (t :: Symbol) (o :: *) :: * where ResolveAsyncResultMethod "bindProperty" o = GObject.Object.ObjectBindPropertyMethodInfo ResolveAsyncResultMethod "bindPropertyFull" o = GObject.Object.ObjectBindPropertyFullMethodInfo ResolveAsyncResultMethod "forceFloating" o = GObject.Object.ObjectForceFloatingMethodInfo ResolveAsyncResultMethod "freezeNotify" o = GObject.Object.ObjectFreezeNotifyMethodInfo ResolveAsyncResultMethod "getv" o = GObject.Object.ObjectGetvMethodInfo ResolveAsyncResultMethod "isFloating" o = GObject.Object.ObjectIsFloatingMethodInfo ResolveAsyncResultMethod "isTagged" o = AsyncResultIsTaggedMethodInfo ResolveAsyncResultMethod "legacyPropagateError" o = AsyncResultLegacyPropagateErrorMethodInfo ResolveAsyncResultMethod "notify" o = GObject.Object.ObjectNotifyMethodInfo ResolveAsyncResultMethod "notifyByPspec" o = GObject.Object.ObjectNotifyByPspecMethodInfo ResolveAsyncResultMethod "ref" o = GObject.Object.ObjectRefMethodInfo ResolveAsyncResultMethod "refSink" o = GObject.Object.ObjectRefSinkMethodInfo ResolveAsyncResultMethod "runDispose" o = GObject.Object.ObjectRunDisposeMethodInfo ResolveAsyncResultMethod "stealData" o = GObject.Object.ObjectStealDataMethodInfo ResolveAsyncResultMethod "stealQdata" o = GObject.Object.ObjectStealQdataMethodInfo ResolveAsyncResultMethod "thawNotify" o = GObject.Object.ObjectThawNotifyMethodInfo ResolveAsyncResultMethod "unref" o = GObject.Object.ObjectUnrefMethodInfo ResolveAsyncResultMethod "watchClosure" o = GObject.Object.ObjectWatchClosureMethodInfo ResolveAsyncResultMethod "getData" o = GObject.Object.ObjectGetDataMethodInfo ResolveAsyncResultMethod "getProperty" o = GObject.Object.ObjectGetPropertyMethodInfo ResolveAsyncResultMethod "getQdata" o = GObject.Object.ObjectGetQdataMethodInfo ResolveAsyncResultMethod "getSourceObject" o = AsyncResultGetSourceObjectMethodInfo ResolveAsyncResultMethod "getUserData" o = AsyncResultGetUserDataMethodInfo ResolveAsyncResultMethod "setData" o = GObject.Object.ObjectSetDataMethodInfo ResolveAsyncResultMethod "setProperty" o = GObject.Object.ObjectSetPropertyMethodInfo ResolveAsyncResultMethod l o = O.MethodResolutionFailed l o instance (info ~ ResolveAsyncResultMethod t AsyncResult, O.MethodInfo info AsyncResult p) => O.IsLabelProxy t (AsyncResult -> p) where fromLabelProxy _ = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info) #if MIN_VERSION_base(4,9,0) instance (info ~ ResolveAsyncResultMethod t AsyncResult, O.MethodInfo info AsyncResult p) => O.IsLabel t (AsyncResult -> 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 #endif -- method AsyncResult::get_source_object -- method type : OrdinaryMethod -- Args : [Arg {argCName = "res", argType = TInterface (Name {namespace = "Gio", name = "AsyncResult"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GAsyncResult", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}] -- Lengths : [] -- returnType : Just (TInterface (Name {namespace = "GObject", name = "Object"})) -- throws : False -- Skip return : False foreign import ccall "g_async_result_get_source_object" g_async_result_get_source_object :: Ptr AsyncResult -> -- res : TInterface (Name {namespace = "Gio", name = "AsyncResult"}) IO (Ptr GObject.Object.Object) {- | Gets the source object from a 'GI.Gio.Interfaces.AsyncResult.AsyncResult'. -} asyncResultGetSourceObject :: (B.CallStack.HasCallStack, MonadIO m, IsAsyncResult a) => a {- ^ /@res@/: a 'GI.Gio.Interfaces.AsyncResult.AsyncResult' -} -> m (Maybe GObject.Object.Object) {- ^ __Returns:__ a new reference to the source object for the /@res@/, or 'Nothing' if there is none. -} asyncResultGetSourceObject res = liftIO $ do res' <- unsafeManagedPtrCastPtr res result <- g_async_result_get_source_object res' maybeResult <- convertIfNonNull result $ \result' -> do result'' <- (wrapObject GObject.Object.Object) result' return result'' touchManagedPtr res return maybeResult #if ENABLE_OVERLOADING data AsyncResultGetSourceObjectMethodInfo instance (signature ~ (m (Maybe GObject.Object.Object)), MonadIO m, IsAsyncResult a) => O.MethodInfo AsyncResultGetSourceObjectMethodInfo a signature where overloadedMethod _ = asyncResultGetSourceObject #endif -- method AsyncResult::get_user_data -- method type : OrdinaryMethod -- Args : [Arg {argCName = "res", argType = TInterface (Name {namespace = "Gio", name = "AsyncResult"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GAsyncResult.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}] -- Lengths : [] -- returnType : Just (TBasicType TPtr) -- throws : False -- Skip return : False foreign import ccall "g_async_result_get_user_data" g_async_result_get_user_data :: Ptr AsyncResult -> -- res : TInterface (Name {namespace = "Gio", name = "AsyncResult"}) IO (Ptr ()) {- | Gets the user data from a 'GI.Gio.Interfaces.AsyncResult.AsyncResult'. -} asyncResultGetUserData :: (B.CallStack.HasCallStack, MonadIO m, IsAsyncResult a) => a {- ^ /@res@/: a 'GI.Gio.Interfaces.AsyncResult.AsyncResult'. -} -> m (Ptr ()) {- ^ __Returns:__ the user data for /@res@/. -} asyncResultGetUserData res = liftIO $ do res' <- unsafeManagedPtrCastPtr res result <- g_async_result_get_user_data res' touchManagedPtr res return result #if ENABLE_OVERLOADING data AsyncResultGetUserDataMethodInfo instance (signature ~ (m (Ptr ())), MonadIO m, IsAsyncResult a) => O.MethodInfo AsyncResultGetUserDataMethodInfo a signature where overloadedMethod _ = asyncResultGetUserData #endif -- method AsyncResult::is_tagged -- method type : OrdinaryMethod -- Args : [Arg {argCName = "res", argType = TInterface (Name {namespace = "Gio", name = "AsyncResult"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GAsyncResult", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "source_tag", argType = TBasicType TPtr, direction = DirectionIn, mayBeNull = True, argDoc = Documentation {rawDocText = Just "an application-defined tag", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}] -- Lengths : [] -- returnType : Just (TBasicType TBoolean) -- throws : False -- Skip return : False foreign import ccall "g_async_result_is_tagged" g_async_result_is_tagged :: Ptr AsyncResult -> -- res : TInterface (Name {namespace = "Gio", name = "AsyncResult"}) Ptr () -> -- source_tag : TBasicType TPtr IO CInt {- | Checks if /@res@/ has the given /@sourceTag@/ (generally a function pointer indicating the function /@res@/ was created by). /Since: 2.34/ -} asyncResultIsTagged :: (B.CallStack.HasCallStack, MonadIO m, IsAsyncResult a) => a {- ^ /@res@/: a 'GI.Gio.Interfaces.AsyncResult.AsyncResult' -} -> Ptr () {- ^ /@sourceTag@/: an application-defined tag -} -> m Bool {- ^ __Returns:__ 'True' if /@res@/ has the indicated /@sourceTag@/, 'False' if not. -} asyncResultIsTagged res sourceTag = liftIO $ do res' <- unsafeManagedPtrCastPtr res result <- g_async_result_is_tagged res' sourceTag let result' = (/= 0) result touchManagedPtr res return result' #if ENABLE_OVERLOADING data AsyncResultIsTaggedMethodInfo instance (signature ~ (Ptr () -> m Bool), MonadIO m, IsAsyncResult a) => O.MethodInfo AsyncResultIsTaggedMethodInfo a signature where overloadedMethod _ = asyncResultIsTagged #endif -- method AsyncResult::legacy_propagate_error -- method type : OrdinaryMethod -- Args : [Arg {argCName = "res", argType = TInterface (Name {namespace = "Gio", name = "AsyncResult"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GAsyncResult", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}] -- Lengths : [] -- returnType : Just (TBasicType TBoolean) -- throws : True -- Skip return : False foreign import ccall "g_async_result_legacy_propagate_error" g_async_result_legacy_propagate_error :: Ptr AsyncResult -> -- res : TInterface (Name {namespace = "Gio", name = "AsyncResult"}) Ptr (Ptr GError) -> -- error IO CInt {- | If /@res@/ is a 'GI.Gio.Objects.SimpleAsyncResult.SimpleAsyncResult', this is equivalent to 'GI.Gio.Objects.SimpleAsyncResult.simpleAsyncResultPropagateError'. Otherwise it returns 'False'. This can be used for legacy error handling in async *@/_finish()/@ wrapper functions that traditionally handled 'GI.Gio.Objects.SimpleAsyncResult.SimpleAsyncResult' error returns themselves rather than calling into the virtual method. This should not be used in new code; 'GI.Gio.Interfaces.AsyncResult.AsyncResult' errors that are set by virtual methods should also be extracted by virtual methods, to enable subclasses to chain up correctly. /Since: 2.34/ -} asyncResultLegacyPropagateError :: (B.CallStack.HasCallStack, MonadIO m, IsAsyncResult a) => a {- ^ /@res@/: a 'GI.Gio.Interfaces.AsyncResult.AsyncResult' -} -> m () {- ^ /(Can throw 'Data.GI.Base.GError.GError')/ -} asyncResultLegacyPropagateError res = liftIO $ do res' <- unsafeManagedPtrCastPtr res onException (do _ <- propagateGError $ g_async_result_legacy_propagate_error res' touchManagedPtr res return () ) (do return () ) #if ENABLE_OVERLOADING data AsyncResultLegacyPropagateErrorMethodInfo instance (signature ~ (m ()), MonadIO m, IsAsyncResult a) => O.MethodInfo AsyncResultLegacyPropagateErrorMethodInfo a signature where overloadedMethod _ = asyncResultLegacyPropagateError #endif