gio/auto/
async_initable.rs

1// This file was generated by gir (https://github.com/gtk-rs/gir)
2// from gir-files (https://github.com/gtk-rs/gir-files)
3// DO NOT EDIT
4
5use crate::{ffi, AsyncResult, Cancellable};
6use glib::{prelude::*, translate::*};
7use std::{boxed::Box as Box_, pin::Pin};
8
9glib::wrapper! {
10    /// `GAsyncInitable` is an interface for asynchronously initializable objects.
11    ///
12    /// This is the asynchronous version of [`Initable`][crate::Initable]; it behaves the same
13    /// in all ways except that initialization is asynchronous. For more details
14    /// see the descriptions on `GInitable`.
15    ///
16    /// A class may implement both the `GInitable` and `GAsyncInitable` interfaces.
17    ///
18    /// Users of objects implementing this are not intended to use the interface
19    /// method directly; instead it will be used automatically in various ways.
20    /// For C applications you generally just call [`new_async()`][Self::new_async()]
21    /// directly, or indirectly via a foo_thing_new_async() wrapper. This will call
22    /// [`AsyncInitableExt::init_async()`][crate::prelude::AsyncInitableExt::init_async()] under the covers, calling back with `NULL`
23    /// and a set `GError` on failure.
24    ///
25    /// A typical implementation might look something like this:
26    ///
27    /// **⚠️ The following code is in c ⚠️**
28    ///
29    /// ```c
30    /// enum {
31    ///    NOT_INITIALIZED,
32    ///    INITIALIZING,
33    ///    INITIALIZED
34    /// };
35    ///
36    /// static void
37    /// _foo_ready_cb (Foo *self)
38    /// {
39    ///   GList *l;
40    ///
41    ///   self->priv->state = INITIALIZED;
42    ///
43    ///   for (l = self->priv->init_results; l != NULL; l = l->next)
44    ///     {
45    ///       GTask *task = l->data;
46    ///
47    ///       if (self->priv->success)
48    ///         g_task_return_boolean (task, TRUE);
49    ///       else
50    ///         g_task_return_new_error (task, ...);
51    ///       g_object_unref (task);
52    ///     }
53    ///
54    ///   g_list_free (self->priv->init_results);
55    ///   self->priv->init_results = NULL;
56    /// }
57    ///
58    /// static void
59    /// foo_init_async (GAsyncInitable       *initable,
60    ///                 int                   io_priority,
61    ///                 GCancellable         *cancellable,
62    ///                 GAsyncReadyCallback   callback,
63    ///                 gpointer              user_data)
64    /// {
65    ///   Foo *self = FOO (initable);
66    ///   GTask *task;
67    ///
68    ///   task = g_task_new (initable, cancellable, callback, user_data);
69    ///   g_task_set_name (task, G_STRFUNC);
70    ///
71    ///   switch (self->priv->state)
72    ///     {
73    ///       case NOT_INITIALIZED:
74    ///         _foo_get_ready (self);
75    ///         self->priv->init_results = g_list_append (self->priv->init_results,
76    ///                                                   task);
77    ///         self->priv->state = INITIALIZING;
78    ///         break;
79    ///       case INITIALIZING:
80    ///         self->priv->init_results = g_list_append (self->priv->init_results,
81    ///                                                   task);
82    ///         break;
83    ///       case INITIALIZED:
84    ///         if (!self->priv->success)
85    ///           g_task_return_new_error (task, ...);
86    ///         else
87    ///           g_task_return_boolean (task, TRUE);
88    ///         g_object_unref (task);
89    ///         break;
90    ///     }
91    /// }
92    ///
93    /// static gboolean
94    /// foo_init_finish (GAsyncInitable       *initable,
95    ///                  GAsyncResult         *result,
96    ///                  GError              **error)
97    /// {
98    ///   g_return_val_if_fail (g_task_is_valid (result, initable), FALSE);
99    ///
100    ///   return g_task_propagate_boolean (G_TASK (result), error);
101    /// }
102    ///
103    /// static void
104    /// foo_async_initable_iface_init (gpointer g_iface,
105    ///                                gpointer data)
106    /// {
107    ///   GAsyncInitableIface *iface = g_iface;
108    ///
109    ///   iface->init_async = foo_init_async;
110    ///   iface->init_finish = foo_init_finish;
111    /// }
112    /// ```
113    ///
114    /// # Implements
115    ///
116    /// [`AsyncInitableExt`][trait@crate::prelude::AsyncInitableExt]
117    #[doc(alias = "GAsyncInitable")]
118    pub struct AsyncInitable(Interface<ffi::GAsyncInitable, ffi::GAsyncInitableIface>);
119
120    match fn {
121        type_ => || ffi::g_async_initable_get_type(),
122    }
123}
124
125impl AsyncInitable {
126    pub const NONE: Option<&'static AsyncInitable> = None;
127}
128
129/// Trait containing all [`struct@AsyncInitable`] methods.
130///
131/// # Implementors
132///
133/// [`AsyncInitable`][struct@crate::AsyncInitable], [`DBusConnection`][struct@crate::DBusConnection], [`DBusProxy`][struct@crate::DBusProxy]
134pub trait AsyncInitableExt: IsA<AsyncInitable> + 'static {
135    /// Starts asynchronous initialization of the object implementing the
136    /// interface. This must be done before any real use of the object after
137    /// initial construction. If the object also implements #GInitable you can
138    /// optionally call g_initable_init() instead.
139    ///
140    /// This method is intended for language bindings. If writing in C,
141    /// g_async_initable_new_async() should typically be used instead.
142    ///
143    /// When the initialization is finished, @callback will be called. You can
144    /// then call g_async_initable_init_finish() to get the result of the
145    /// initialization.
146    ///
147    /// Implementations may also support cancellation. If @cancellable is not
148    /// [`None`], then initialization can be cancelled by triggering the cancellable
149    /// object from another thread. If the operation was cancelled, the error
150    /// [`IOErrorEnum::Cancelled`][crate::IOErrorEnum::Cancelled] will be returned. If @cancellable is not [`None`], and
151    /// the object doesn't support cancellable initialization, the error
152    /// [`IOErrorEnum::NotSupported`][crate::IOErrorEnum::NotSupported] will be returned.
153    ///
154    /// As with #GInitable, if the object is not initialized, or initialization
155    /// returns with an error, then all operations on the object except
156    /// g_object_ref() and g_object_unref() are considered to be invalid, and
157    /// have undefined behaviour. They will often fail with g_critical() or
158    /// g_warning(), but this must not be relied on.
159    ///
160    /// Callers should not assume that a class which implements #GAsyncInitable can
161    /// be initialized multiple times; for more information, see g_initable_init().
162    /// If a class explicitly supports being initialized multiple times,
163    /// implementation requires yielding all subsequent calls to init_async() on the
164    /// results of the first call.
165    ///
166    /// For classes that also support the #GInitable interface, the default
167    /// implementation of this method will run the g_initable_init() function
168    /// in a thread, so if you want to support asynchronous initialization via
169    /// threads, just implement the #GAsyncInitable interface without overriding
170    /// any interface methods.
171    /// ## `io_priority`
172    /// the [I/O priority](iface.AsyncResult.html#io-priority) of the operation
173    /// ## `cancellable`
174    /// optional #GCancellable object, [`None`] to ignore.
175    /// ## `callback`
176    /// a #GAsyncReadyCallback to call when the request is satisfied
177    #[doc(alias = "g_async_initable_init_async")]
178    unsafe fn init_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
179        &self,
180        io_priority: glib::Priority,
181        cancellable: Option<&impl IsA<Cancellable>>,
182        callback: P,
183    ) {
184        let main_context = glib::MainContext::ref_thread_default();
185        let is_main_context_owner = main_context.is_owner();
186        let has_acquired_main_context = (!is_main_context_owner)
187            .then(|| main_context.acquire().ok())
188            .flatten();
189        assert!(
190            is_main_context_owner || has_acquired_main_context.is_some(),
191            "Async operations only allowed if the thread is owning the MainContext"
192        );
193
194        let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
195            Box_::new(glib::thread_guard::ThreadGuard::new(callback));
196        unsafe extern "C" fn init_async_trampoline<P: FnOnce(Result<(), glib::Error>) + 'static>(
197            _source_object: *mut glib::gobject_ffi::GObject,
198            res: *mut crate::ffi::GAsyncResult,
199            user_data: glib::ffi::gpointer,
200        ) {
201            let mut error = std::ptr::null_mut();
202            let _ = ffi::g_async_initable_init_finish(_source_object as *mut _, res, &mut error);
203            let result = if error.is_null() {
204                Ok(())
205            } else {
206                Err(from_glib_full(error))
207            };
208            let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
209                Box_::from_raw(user_data as *mut _);
210            let callback: P = callback.into_inner();
211            callback(result);
212        }
213        let callback = init_async_trampoline::<P>;
214        ffi::g_async_initable_init_async(
215            self.as_ref().to_glib_none().0,
216            io_priority.into_glib(),
217            cancellable.map(|p| p.as_ref()).to_glib_none().0,
218            Some(callback),
219            Box_::into_raw(user_data) as *mut _,
220        );
221    }
222
223    unsafe fn init_future(
224        &self,
225        io_priority: glib::Priority,
226    ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
227        Box_::pin(crate::GioFuture::new(
228            self,
229            move |obj, cancellable, send| {
230                obj.init_async(io_priority, Some(cancellable), move |res| {
231                    send.resolve(res);
232                });
233            },
234        ))
235    }
236}
237
238impl<O: IsA<AsyncInitable>> AsyncInitableExt for O {}