// Package gio was automatically generated by github.com/bnema/puregotk DO NOT EDIT package gio import ( "structs" "unsafe" "github.com/ebitengine/purego" "github.com/bnema/puregotk/pkg/core" "github.com/bnema/puregotk/v4/glib" "github.com/bnema/puregotk/v4/gobject" "github.com/bnema/puregotk/v4/gobject/types" ) // The prototype for a task function to be run in a thread via // g_task_run_in_thread() or g_task_run_in_thread_sync(). // // If the return-on-cancel flag is set on @task, and @cancellable gets // cancelled, then the #GTask will be completed immediately (as though // g_task_return_error_if_cancelled() had been called), without // waiting for the task function to complete. However, the task // function will continue running in its thread in the background. The // function therefore needs to be careful about how it uses // externally-visible state in this case. See // g_task_set_return_on_cancel() for more details. // // Other than in that case, @task will be completed when the // #GTaskThreadFunc returns, not when it calls a // `g_task_return_` function. type TaskThreadFunc func(uintptr, uintptr, uintptr, uintptr) type TaskClass struct { _ structs.HostLayout } func (x *TaskClass) GoPointer() uintptr { return uintptr(unsafe.Pointer(x)) } // A `GTask` represents and manages a cancellable ‘task’. // // ## Asynchronous operations // // The most common usage of `GTask` is as a [iface@Gio.AsyncResult], to // manage data during an asynchronous operation. You call // [ctor@Gio.Task.new] in the ‘start’ method, followed by // [method@Gio.Task.set_task_data] and the like if you need to keep some // additional data associated with the task, and then pass the // task object around through your asynchronous operation. // Eventually, you will call a method such as // [method@Gio.Task.return_pointer] or [method@Gio.Task.return_error], which // will save the value you give it and then invoke the task’s callback // function in the thread-default main context (see // [method@GLib.MainContext.push_thread_default]) // where it was created (waiting until the next iteration of the main // loop first, if necessary). The caller will pass the `GTask` back to // the operation’s finish function (as a [iface@Gio.AsyncResult]), and you can // use [method@Gio.Task.propagate_pointer] or the like to extract the // return value. // // Using `GTask` requires the thread-default [struct@GLib.MainContext] from when // the `GTask` was constructed to be running at least until the task has // completed and its data has been freed. // // If a `GTask` has been constructed and its callback set, it is an error to // not call `g_task_return_*()` on it. GLib will warn at runtime if this happens // (since 2.76). // // Here is an example for using `GTask` as a [iface@Gio.AsyncResult]: // ```c // // typedef struct { // CakeFrostingType frosting; // char *message; // } DecorationData; // // static void // decoration_data_free (DecorationData *decoration) // // { // g_free (decoration->message); // g_slice_free (DecorationData, decoration); // } // // static void // baked_cb (Cake *cake, // // gpointer user_data) // // { // GTask *task = user_data; // DecorationData *decoration = g_task_get_task_data (task); // GError *error = NULL; // // if (cake == NULL) // { // g_task_return_new_error (task, BAKER_ERROR, BAKER_ERROR_NO_FLOUR, // "Go to the supermarket"); // g_object_unref (task); // return; // } // // if (!cake_decorate (cake, decoration->frosting, decoration->message, &error)) // { // g_object_unref (cake); // // g_task_return_error() takes ownership of error // g_task_return_error (task, error); // g_object_unref (task); // return; // } // // g_task_return_pointer (task, cake, g_object_unref); // g_object_unref (task); // } // // void // baker_bake_cake_async (Baker *self, // // guint radius, // CakeFlavor flavor, // CakeFrostingType frosting, // const char *message, // GCancellable *cancellable, // GAsyncReadyCallback callback, // gpointer user_data) // // { // GTask *task; // DecorationData *decoration; // Cake *cake; // // task = g_task_new (self, cancellable, callback, user_data); // if (radius < 3) // { // g_task_return_new_error (task, BAKER_ERROR, BAKER_ERROR_TOO_SMALL, // "%ucm radius cakes are silly", // radius); // g_object_unref (task); // return; // } // // cake = _baker_get_cached_cake (self, radius, flavor, frosting, message); // if (cake != NULL) // { // // _baker_get_cached_cake() returns a reffed cake // g_task_return_pointer (task, cake, g_object_unref); // g_object_unref (task); // return; // } // // decoration = g_slice_new (DecorationData); // decoration->frosting = frosting; // decoration->message = g_strdup (message); // g_task_set_task_data (task, decoration, (GDestroyNotify) decoration_data_free); // // _baker_begin_cake (self, radius, flavor, cancellable, baked_cb, task); // } // // Cake * // baker_bake_cake_finish (Baker *self, // // GAsyncResult *result, // GError **error) // // { // g_return_val_if_fail (g_task_is_valid (result, self), NULL); // // return g_task_propagate_pointer (G_TASK (result), error); // } // // ``` // // ## Chained asynchronous operations // // `GTask` also tries to simplify asynchronous operations that // internally chain together several smaller asynchronous // operations. [method@Gio.Task.get_cancellable], [method@Gio.Task.get_context], // and [method@Gio.Task.get_priority] allow you to get back the task’s // [class@Gio.Cancellable], [struct@GLib.MainContext], and // [I/O priority](iface.AsyncResult.html#io-priority) // when starting a new subtask, so you don’t have to keep track // of them yourself. [method@Gio.Task.attach_source] simplifies the case // of waiting for a source to fire (automatically using the correct // [struct@GLib.MainContext] and priority). // // Here is an example for chained asynchronous operations: // ```c // // typedef struct { // Cake *cake; // CakeFrostingType frosting; // char *message; // } BakingData; // // static void // decoration_data_free (BakingData *bd) // // { // if (bd->cake) // g_object_unref (bd->cake); // g_free (bd->message); // g_slice_free (BakingData, bd); // } // // static void // decorated_cb (Cake *cake, // // GAsyncResult *result, // gpointer user_data) // // { // GTask *task = user_data; // GError *error = NULL; // // if (!cake_decorate_finish (cake, result, &error)) // { // g_object_unref (cake); // g_task_return_error (task, error); // g_object_unref (task); // return; // } // // // baking_data_free() will drop its ref on the cake, so we have to // // take another here to give to the caller. // g_task_return_pointer (task, g_object_ref (cake), g_object_unref); // g_object_unref (task); // } // // static gboolean // decorator_ready (gpointer user_data) // // { // GTask *task = user_data; // BakingData *bd = g_task_get_task_data (task); // // cake_decorate_async (bd->cake, bd->frosting, bd->message, // g_task_get_cancellable (task), // decorated_cb, task); // // return G_SOURCE_REMOVE; // } // // static void // baked_cb (Cake *cake, // // gpointer user_data) // // { // GTask *task = user_data; // BakingData *bd = g_task_get_task_data (task); // GError *error = NULL; // // if (cake == NULL) // { // g_task_return_new_error (task, BAKER_ERROR, BAKER_ERROR_NO_FLOUR, // "Go to the supermarket"); // g_object_unref (task); // return; // } // // bd->cake = cake; // // // Bail out now if the user has already cancelled // if (g_task_return_error_if_cancelled (task)) // { // g_object_unref (task); // return; // } // // if (cake_decorator_available (cake)) // decorator_ready (task); // else // { // GSource *source; // // source = cake_decorator_wait_source_new (cake); // // Attach @source to @task’s GMainContext and have it call // // decorator_ready() when it is ready. // g_task_attach_source (task, source, decorator_ready); // g_source_unref (source); // } // } // // void // baker_bake_cake_async (Baker *self, // // guint radius, // CakeFlavor flavor, // CakeFrostingType frosting, // const char *message, // gint priority, // GCancellable *cancellable, // GAsyncReadyCallback callback, // gpointer user_data) // // { // GTask *task; // BakingData *bd; // // task = g_task_new (self, cancellable, callback, user_data); // g_task_set_priority (task, priority); // // bd = g_slice_new0 (BakingData); // bd->frosting = frosting; // bd->message = g_strdup (message); // g_task_set_task_data (task, bd, (GDestroyNotify) baking_data_free); // // _baker_begin_cake (self, radius, flavor, cancellable, baked_cb, task); // } // // Cake * // baker_bake_cake_finish (Baker *self, // // GAsyncResult *result, // GError **error) // // { // g_return_val_if_fail (g_task_is_valid (result, self), NULL); // // return g_task_propagate_pointer (G_TASK (result), error); // } // // ``` // // ## Asynchronous operations from synchronous ones // // You can use [method@Gio.Task.run_in_thread] to turn a synchronous // operation into an asynchronous one, by running it in a thread. // When it completes, the result will be dispatched to the thread-default // main context (see [method@GLib.MainContext.push_thread_default]) // where the `GTask` was created. // // Running a task in a thread: // ```c // // typedef struct { // guint radius; // CakeFlavor flavor; // CakeFrostingType frosting; // char *message; // } CakeData; // // static void // cake_data_free (CakeData *cake_data) // // { // g_free (cake_data->message); // g_slice_free (CakeData, cake_data); // } // // static void // bake_cake_thread (GTask *task, // // gpointer source_object, // gpointer task_data, // GCancellable *cancellable) // // { // Baker *self = source_object; // CakeData *cake_data = task_data; // Cake *cake; // GError *error = NULL; // // cake = bake_cake (baker, cake_data->radius, cake_data->flavor, // cake_data->frosting, cake_data->message, // cancellable, &error); // if (cake) // g_task_return_pointer (task, cake, g_object_unref); // else // g_task_return_error (task, error); // } // // void // baker_bake_cake_async (Baker *self, // // guint radius, // CakeFlavor flavor, // CakeFrostingType frosting, // const char *message, // GCancellable *cancellable, // GAsyncReadyCallback callback, // gpointer user_data) // // { // CakeData *cake_data; // GTask *task; // // cake_data = g_slice_new (CakeData); // cake_data->radius = radius; // cake_data->flavor = flavor; // cake_data->frosting = frosting; // cake_data->message = g_strdup (message); // task = g_task_new (self, cancellable, callback, user_data); // g_task_set_task_data (task, cake_data, (GDestroyNotify) cake_data_free); // g_task_run_in_thread (task, bake_cake_thread); // g_object_unref (task); // } // // Cake * // baker_bake_cake_finish (Baker *self, // // GAsyncResult *result, // GError **error) // // { // g_return_val_if_fail (g_task_is_valid (result, self), NULL); // // return g_task_propagate_pointer (G_TASK (result), error); // } // // ``` // // ## Adding cancellability to uncancellable tasks // // Finally, [method@Gio.Task.run_in_thread] and // [method@Gio.Task.run_in_thread_sync] can be used to turn an uncancellable // operation into a cancellable one. If you call // [method@Gio.Task.set_return_on_cancel], passing `TRUE`, then if the task’s // [class@Gio.Cancellable] is cancelled, it will return control back to the // caller immediately, while allowing the task thread to continue running in the // background (and simply discarding its result when it finally does finish). // Provided that the task thread is careful about how it uses // locks and other externally-visible resources, this allows you // to make ‘GLib-friendly’ asynchronous and cancellable // synchronous variants of blocking APIs. // // Cancelling a task: // ```c // static void // bake_cake_thread (GTask *task, // // gpointer source_object, // gpointer task_data, // GCancellable *cancellable) // // { // Baker *self = source_object; // CakeData *cake_data = task_data; // Cake *cake; // GError *error = NULL; // // cake = bake_cake (baker, cake_data->radius, cake_data->flavor, // cake_data->frosting, cake_data->message, // &error); // if (error) // { // g_task_return_error (task, error); // return; // } // // // If the task has already been cancelled, then we don’t want to add // // the cake to the cake cache. Likewise, we don’t want to have the // // task get cancelled in the middle of updating the cache. // // g_task_set_return_on_cancel() will return %TRUE here if it managed // // to disable return-on-cancel, or %FALSE if the task was cancelled // // before it could. // if (g_task_set_return_on_cancel (task, FALSE)) // { // // If the caller cancels at this point, their // // GAsyncReadyCallback won’t be invoked until we return, // // so we don’t have to worry that this code will run at // // the same time as that code does. But if there were // // other functions that might look at the cake cache, // // then we’d probably need a GMutex here as well. // baker_add_cake_to_cache (baker, cake); // g_task_return_pointer (task, cake, g_object_unref); // } // } // // void // baker_bake_cake_async (Baker *self, // // guint radius, // CakeFlavor flavor, // CakeFrostingType frosting, // const char *message, // GCancellable *cancellable, // GAsyncReadyCallback callback, // gpointer user_data) // // { // CakeData *cake_data; // GTask *task; // // cake_data = g_slice_new (CakeData); // // ... // // task = g_task_new (self, cancellable, callback, user_data); // g_task_set_task_data (task, cake_data, (GDestroyNotify) cake_data_free); // g_task_set_return_on_cancel (task, TRUE); // g_task_run_in_thread (task, bake_cake_thread); // } // // Cake * // baker_bake_cake_sync (Baker *self, // // guint radius, // CakeFlavor flavor, // CakeFrostingType frosting, // const char *message, // GCancellable *cancellable, // GError **error) // // { // CakeData *cake_data; // GTask *task; // Cake *cake; // // cake_data = g_slice_new (CakeData); // // ... // // task = g_task_new (self, cancellable, NULL, NULL); // g_task_set_task_data (task, cake_data, (GDestroyNotify) cake_data_free); // g_task_set_return_on_cancel (task, TRUE); // g_task_run_in_thread_sync (task, bake_cake_thread); // // cake = g_task_propagate_pointer (task, error); // g_object_unref (task); // return cake; // } // // ``` // // ## Porting from [class@Gio.SimpleAsyncResult] // // `GTask`’s API attempts to be simpler than [class@Gio.SimpleAsyncResult]’s // in several ways: // // - You can save task-specific data with [method@Gio.Task.set_task_data], and // retrieve it later with [method@Gio.Task.get_task_data]. This replaces the // abuse of [method@Gio.SimpleAsyncResult.set_op_res_gpointer] for the same // purpose with [class@Gio.SimpleAsyncResult]. // - In addition to the task data, `GTask` also keeps track of the // [priority](iface.AsyncResult.html#io-priority), [class@Gio.Cancellable], // and [struct@GLib.MainContext] associated with the task, so tasks that // consist of a chain of simpler asynchronous operations will have easy access // to those values when starting each sub-task. // - [method@Gio.Task.return_error_if_cancelled] provides simplified // handling for cancellation. In addition, cancellation // overrides any other `GTask` return value by default, like // [class@Gio.SimpleAsyncResult] does when // [method@Gio.SimpleAsyncResult.set_check_cancellable] is called. // (You can use [method@Gio.Task.set_check_cancellable] to turn off that // behavior.) On the other hand, [method@Gio.Task.run_in_thread] // guarantees that it will always run your // `task_func`, even if the task’s [class@Gio.Cancellable] // is already cancelled before the task gets a chance to run; // you can start your `task_func` with a // [method@Gio.Task.return_error_if_cancelled] check if you need the // old behavior. // - The ‘return’ methods (eg, [method@Gio.Task.return_pointer]) // automatically cause the task to be ‘completed’ as well, and // there is no need to worry about the ‘complete’ vs ‘complete in idle’ // distinction. (`GTask` automatically figures out // whether the task’s callback can be invoked directly, or // if it needs to be sent to another [struct@GLib.MainContext], or delayed // until the next iteration of the current [struct@GLib.MainContext].) // - The ‘finish’ functions for `GTask` based operations are generally // much simpler than [class@Gio.SimpleAsyncResult] ones, normally consisting // of only a single call to [method@Gio.Task.propagate_pointer] or the like. // Since [method@Gio.Task.propagate_pointer] ‘steals’ the return value from // the `GTask`, it is not necessary to juggle pointers around to // prevent it from being freed twice. // - With [class@Gio.SimpleAsyncResult], it was common to call // [method@Gio.SimpleAsyncResult.propagate_error] from the // `_finish()` wrapper function, and have // virtual method implementations only deal with successful // returns. This behavior is deprecated, because it makes it // difficult for a subclass to chain to a parent class’s async // methods. Instead, the wrapper function should just be a // simple wrapper, and the virtual method should call an // appropriate `g_task_propagate_` function. // Note that wrapper methods can now use // [method@Gio.AsyncResult.legacy_propagate_error] to do old-style // [class@Gio.SimpleAsyncResult] error-returning behavior, and // [method@Gio.AsyncResult.is_tagged] to check if a result is tagged as // having come from the `_async()` wrapper // function (for ‘short-circuit’ results, such as when passing // `0` to [method@Gio.InputStream.read_async]). // // ## Thread-safety considerations // // Due to some infelicities in the API design, there is a // thread-safety concern that users of `GTask` have to be aware of: // // If the `main` thread drops its last reference to the source object // or the task data before the task is finalized, then the finalizers // of these objects may be called on the worker thread. // // This is a problem if the finalizers use non-threadsafe API, and // can lead to hard-to-debug crashes. Possible workarounds include: // // - Clear task data in a signal handler for `notify::completed` // - Keep iterating a main context in the main thread and defer // dropping the reference to the source object to that main // context when the task is finalized type Task struct { gobject.Object } var xTaskGLibType func() types.GType func TaskGLibType() types.GType { return xTaskGLibType() } func TaskNewFromInternalPtr(ptr uintptr) *Task { cls := &Task{} cls.Ptr = ptr return cls } var xNewTask func(uintptr, uintptr, uintptr, uintptr) uintptr // Creates a #GTask acting on @source_object, which will eventually be // used to invoke @callback in the current thread-default main context // (see [method@GLib.MainContext.push_thread_default]). // // Call this in the "start" method of your asynchronous method, and // pass the #GTask around throughout the asynchronous operation. You // can use g_task_set_task_data() to attach task-specific data to the // object, which you can retrieve later via g_task_get_task_data(). // // By default, if @cancellable is cancelled, then the return value of // the task will always be %G_IO_ERROR_CANCELLED, even if the task had // already completed before the cancellation. This allows for // simplified handling in cases where cancellation may imply that // other objects that the task depends on have been destroyed. If you // do not want this behavior, you can use // g_task_set_check_cancellable() to change it. func NewTask(SourceObjectVar *gobject.Object, CancellableVar *Cancellable, CallbackVar *AsyncReadyCallback, CallbackDataVar uintptr) *Task { var cls *Task var CallbackVarRef uintptr if CallbackVar != nil { CallbackVarPtr := uintptr(unsafe.Pointer(CallbackVar)) if cbRefPtr, ok := glib.GetCallback(CallbackVarPtr); ok { CallbackVarRef = cbRefPtr } else { fcb := func(arg0 uintptr, arg1 uintptr, arg2 uintptr) { cbFn := *CallbackVar cbFn(arg0, arg1, arg2) } CallbackVarRef = purego.NewCallback(fcb) glib.SaveCallbackWithClosure(CallbackVarPtr, CallbackVarRef, CallbackVar) } } cret := xNewTask(SourceObjectVar.GoPointer(), CancellableVar.GoPointer(), CallbackVarRef, CallbackDataVar) if cret == 0 { return nil } cls = &Task{} cls.Ptr = cret return cls } var xTaskAttachSource func(uintptr, *glib.Source, uintptr) // A utility function for dealing with async operations where you need // to wait for a #GSource to trigger. Attaches @source to @task's // #GMainContext with @task's [priority](iface.AsyncResult.html#io-priority), // and sets @source's callback to @callback, with @task as the callback's // `user_data`. // // It will set the @source’s name to the task’s name (as set with // g_task_set_name()), if one has been set on the task and the source doesn’t // yet have a name. // // This takes a reference on @task until @source is destroyed. func (x *Task) AttachSource(SourceVar *glib.Source, CallbackVar *glib.SourceFunc) { var CallbackVarRef uintptr if CallbackVar != nil { CallbackVarPtr := uintptr(unsafe.Pointer(CallbackVar)) if cbRefPtr, ok := glib.GetCallback(CallbackVarPtr); ok { CallbackVarRef = cbRefPtr } else { fcb := func(arg0 uintptr) bool { cbFn := *CallbackVar return cbFn(arg0) } CallbackVarRef = purego.NewCallback(fcb) glib.SaveCallbackWithClosure(CallbackVarPtr, CallbackVarRef, CallbackVar) } } xTaskAttachSource(x.GoPointer(), SourceVar, CallbackVarRef) } var xTaskGetCancellable func(uintptr) uintptr // Gets @task's #GCancellable func (x *Task) GetCancellable() *Cancellable { var cls *Cancellable cret := xTaskGetCancellable(x.GoPointer()) if cret == 0 { return nil } gobject.IncreaseRef(cret) cls = &Cancellable{} cls.Ptr = cret return cls } var xTaskGetCheckCancellable func(uintptr) bool // Gets @task's check-cancellable flag. See // g_task_set_check_cancellable() for more details. func (x *Task) GetCheckCancellable() bool { cret := xTaskGetCheckCancellable(x.GoPointer()) return cret } var xTaskGetCompleted func(uintptr) bool // Gets the value of #GTask:completed. This changes from %FALSE to %TRUE after // the task’s callback is invoked, and will return %FALSE if called from inside // the callback. func (x *Task) GetCompleted() bool { cret := xTaskGetCompleted(x.GoPointer()) return cret } var xTaskGetContext func(uintptr) *glib.MainContext // Gets the #GMainContext that @task will return its result in (that // is, the context that was the thread-default main context // (see [method@GLib.MainContext.push_thread_default]) // at the point when @task was created). // // This will always return a non-%NULL value, even if the task's // context is the default #GMainContext. func (x *Task) GetContext() *glib.MainContext { cret := xTaskGetContext(x.GoPointer()) return cret } var xTaskGetName func(uintptr) string // Gets @task’s name. See g_task_set_name(). func (x *Task) GetName() string { cret := xTaskGetName(x.GoPointer()) return cret } var xTaskGetPriority func(uintptr) int // Gets @task's priority func (x *Task) GetPriority() int { cret := xTaskGetPriority(x.GoPointer()) return cret } var xTaskGetReturnOnCancel func(uintptr) bool // Gets @task's return-on-cancel flag. See // g_task_set_return_on_cancel() for more details. func (x *Task) GetReturnOnCancel() bool { cret := xTaskGetReturnOnCancel(x.GoPointer()) return cret } var xTaskGetSourceObject func(uintptr) uintptr // Gets the source object from @task. Like // g_async_result_get_source_object(), but does not ref the object. func (x *Task) GetSourceObject() *gobject.Object { var cls *gobject.Object cret := xTaskGetSourceObject(x.GoPointer()) if cret == 0 { return nil } gobject.IncreaseRef(cret) cls = &gobject.Object{} cls.Ptr = cret return cls } var xTaskGetSourceTag func(uintptr) uintptr // Gets @task's source tag. See g_task_set_source_tag(). func (x *Task) GetSourceTag() uintptr { cret := xTaskGetSourceTag(x.GoPointer()) return cret } var xTaskGetTaskData func(uintptr) uintptr // Gets @task's `task_data`. func (x *Task) GetTaskData() uintptr { cret := xTaskGetTaskData(x.GoPointer()) return cret } var xTaskHadError func(uintptr) bool // Tests if @task resulted in an error. func (x *Task) HadError() bool { cret := xTaskHadError(x.GoPointer()) return cret } var xTaskPropagateBoolean func(uintptr) bool // Gets the result of @task as a #gboolean. // // If the task resulted in an error, or was cancelled, then this will // instead return %FALSE and set @error. // // Since this method transfers ownership of the return value (or // error) to the caller, you may only call it once. func (x *Task) PropagateBoolean() (bool, error) { var cerr *glib.Error cret := xTaskPropagateBoolean(x.GoPointer()) if cerr == nil { return cret, nil } return cret, cerr } var xTaskPropagateInt func(uintptr) int // Gets the result of @task as an integer (#gssize). // // If the task resulted in an error, or was cancelled, then this will // instead return -1 and set @error. // // Since this method transfers ownership of the return value (or // error) to the caller, you may only call it once. func (x *Task) PropagateInt() (int, error) { var cerr *glib.Error cret := xTaskPropagateInt(x.GoPointer()) if cerr == nil { return cret, nil } return cret, cerr } var xTaskPropagatePointer func(uintptr) uintptr // Gets the result of @task as a pointer, and transfers ownership // of that value to the caller. // // If the task resulted in an error, or was cancelled, then this will // instead return %NULL and set @error. // // Since this method transfers ownership of the return value (or // error) to the caller, you may only call it once. func (x *Task) PropagatePointer() (uintptr, error) { var cerr *glib.Error cret := xTaskPropagatePointer(x.GoPointer()) if cerr == nil { return cret, nil } return cret, cerr } var xTaskPropagateValue func(uintptr, *gobject.Value, **glib.Error) bool // Gets the result of @task as a #GValue, and transfers ownership of // that value to the caller. As with g_task_return_value(), this is // a generic low-level method; g_task_propagate_pointer() and the like // will usually be more useful for C code. // // If the task resulted in an error, or was cancelled, then this will // instead set @error and return %FALSE. // // Since this method transfers ownership of the return value (or // error) to the caller, you may only call it once. func (x *Task) PropagateValue(ValueVar *gobject.Value) (bool, error) { var cerr *glib.Error cret := xTaskPropagateValue(x.GoPointer(), ValueVar, &cerr) if cerr == nil { return cret, nil } return cret, cerr } var xTaskReturnBoolean func(uintptr, bool) // Sets @task's result to @result and completes the task (see // g_task_return_pointer() for more discussion of exactly what this // means). func (x *Task) ReturnBoolean(ResultVar bool) { xTaskReturnBoolean(x.GoPointer(), ResultVar) } var xTaskReturnError func(uintptr, *glib.Error) // Sets @task's result to @error (which @task assumes ownership of) // and completes the task (see g_task_return_pointer() for more // discussion of exactly what this means). // // Note that since the task takes ownership of @error, and since the // task may be completed before returning from g_task_return_error(), // you cannot assume that @error is still valid after calling this. // Call g_error_copy() on the error if you need to keep a local copy // as well. // // See also [method@Gio.Task.return_new_error], // [method@Gio.Task.return_new_error_literal]. func (x *Task) ReturnError(ErrorVar *glib.Error) { xTaskReturnError(x.GoPointer(), ErrorVar) } var xTaskReturnErrorIfCancelled func(uintptr) bool // Checks if @task's #GCancellable has been cancelled, and if so, sets // @task's error accordingly and completes the task (see // g_task_return_pointer() for more discussion of exactly what this // means). func (x *Task) ReturnErrorIfCancelled() bool { cret := xTaskReturnErrorIfCancelled(x.GoPointer()) return cret } var xTaskReturnInt func(uintptr, int) // Sets @task's result to @result and completes the task (see // g_task_return_pointer() for more discussion of exactly what this // means). func (x *Task) ReturnInt(ResultVar int) { xTaskReturnInt(x.GoPointer(), ResultVar) } var xTaskReturnNewError func(uintptr, glib.Quark, int, string, ...interface{}) // Sets @task's result to a new #GError created from @domain, @code, // @format, and the remaining arguments, and completes the task (see // g_task_return_pointer() for more discussion of exactly what this // means). // // See also g_task_return_error(). func (x *Task) ReturnNewError(DomainVar glib.Quark, CodeVar int, FormatVar string, varArgs ...interface{}) { xTaskReturnNewError(x.GoPointer(), DomainVar, CodeVar, FormatVar, varArgs...) } var xTaskReturnNewErrorLiteral func(uintptr, glib.Quark, int, string) // Sets @task’s result to a new [type@GLib.Error] created from @domain, @code, // @message and completes the task. // // See [method@Gio.Task.return_pointer] for more discussion of exactly what // ‘completing the task’ means. // // See also [method@Gio.Task.return_new_error]. func (x *Task) ReturnNewErrorLiteral(DomainVar glib.Quark, CodeVar int, MessageVar string) { xTaskReturnNewErrorLiteral(x.GoPointer(), DomainVar, CodeVar, MessageVar) } var xTaskReturnPointer func(uintptr, uintptr, uintptr) // Sets @task's result to @result and completes the task. If @result // is not %NULL, then @result_destroy will be used to free @result if // the caller does not take ownership of it with // g_task_propagate_pointer(). // // "Completes the task" means that for an ordinary asynchronous task // it will either invoke the task's callback, or else queue that // callback to be invoked in the proper #GMainContext, or in the next // iteration of the current #GMainContext. For a task run via // g_task_run_in_thread() or g_task_run_in_thread_sync(), calling this // method will save @result to be returned to the caller later, but // the task will not actually be completed until the #GTaskThreadFunc // exits. // // Note that since the task may be completed before returning from // g_task_return_pointer(), you cannot assume that @result is still // valid after calling this, unless you are still holding another // reference on it. func (x *Task) ReturnPointer(ResultVar uintptr, ResultDestroyVar *glib.DestroyNotify) { var ResultDestroyVarRef uintptr if ResultDestroyVar != nil { ResultDestroyVarPtr := uintptr(unsafe.Pointer(ResultDestroyVar)) if cbRefPtr, ok := glib.GetCallback(ResultDestroyVarPtr); ok { ResultDestroyVarRef = cbRefPtr } else { fcb := func(arg0 uintptr) { cbFn := *ResultDestroyVar cbFn(arg0) } ResultDestroyVarRef = purego.NewCallback(fcb) glib.SaveCallbackWithClosure(ResultDestroyVarPtr, ResultDestroyVarRef, ResultDestroyVar) } } xTaskReturnPointer(x.GoPointer(), ResultVar, ResultDestroyVarRef) } var xTaskReturnPrefixedError func(uintptr, *glib.Error, string, ...interface{}) // Sets @task's result to @error (which @task assumes ownership of), with // the message prefixed according to @format, and completes the task // (see g_task_return_pointer() for more discussion of exactly what this // means). // // Note that since the task takes ownership of @error, and since the // task may be completed before returning from g_task_return_prefixed_error(), // you cannot assume that @error is still valid after calling this. // Call g_error_copy() on the error if you need to keep a local copy // as well. // // See also g_task_return_error(), g_prefix_error(). func (x *Task) ReturnPrefixedError(ErrorVar *glib.Error, FormatVar string, varArgs ...interface{}) { xTaskReturnPrefixedError(x.GoPointer(), ErrorVar, FormatVar, varArgs...) } var xTaskReturnValue func(uintptr, *gobject.Value) // Sets @task's result to @result (by copying it) and completes the task. // // If @result is %NULL then a #GValue of type %G_TYPE_POINTER // with a value of %NULL will be used for the result. // // This is a very generic low-level method intended primarily for use // by language bindings; for C code, g_task_return_pointer() and the // like will normally be much easier to use. func (x *Task) ReturnValue(ResultVar *gobject.Value) { xTaskReturnValue(x.GoPointer(), ResultVar) } var xTaskRunInThread func(uintptr, uintptr) // Runs @task_func in another thread. When @task_func returns, @task's // #GAsyncReadyCallback will be invoked in @task's #GMainContext. // // This takes a ref on @task until the task completes. // // See #GTaskThreadFunc for more details about how @task_func is handled. // // Although GLib currently rate-limits the tasks queued via // g_task_run_in_thread(), you should not assume that it will always // do this. If you have a very large number of tasks to run (several tens of // tasks), but don't want them to all run at once, you should only queue a // limited number of them (around ten) at a time. // // Be aware that if your task depends on other tasks to complete, use of this // function could lead to a livelock if the other tasks also use this function // and enough of them (around 10) execute in a dependency chain, as that will // exhaust the thread pool. If this situation is possible, consider using a // separate worker thread or thread pool explicitly, rather than using // g_task_run_in_thread(). func (x *Task) RunInThread(TaskFuncVar *TaskThreadFunc) { var TaskFuncVarRef uintptr if TaskFuncVar != nil { TaskFuncVarPtr := uintptr(unsafe.Pointer(TaskFuncVar)) if cbRefPtr, ok := glib.GetCallback(TaskFuncVarPtr); ok { TaskFuncVarRef = cbRefPtr } else { fcb := func(arg0 uintptr, arg1 uintptr, arg2 uintptr, arg3 uintptr) { cbFn := *TaskFuncVar cbFn(arg0, arg1, arg2, arg3) } TaskFuncVarRef = purego.NewCallback(fcb) glib.SaveCallbackWithClosure(TaskFuncVarPtr, TaskFuncVarRef, TaskFuncVar) } } xTaskRunInThread(x.GoPointer(), TaskFuncVarRef) } var xTaskRunInThreadSync func(uintptr, uintptr) // Runs @task_func in another thread, and waits for it to return or be // cancelled. You can use g_task_propagate_pointer(), etc, afterward // to get the result of @task_func. // // See #GTaskThreadFunc for more details about how @task_func is handled. // // Normally this is used with tasks created with a %NULL // `callback`, but note that even if the task does // have a callback, it will not be invoked when @task_func returns. // #GTask:completed will be set to %TRUE just before this function returns. // // Although GLib currently rate-limits the tasks queued via // g_task_run_in_thread_sync(), you should not assume that it will // always do this. If you have a very large number of tasks to run, // but don't want them to all run at once, you should only queue a // limited number of them at a time. func (x *Task) RunInThreadSync(TaskFuncVar *TaskThreadFunc) { var TaskFuncVarRef uintptr if TaskFuncVar != nil { TaskFuncVarPtr := uintptr(unsafe.Pointer(TaskFuncVar)) if cbRefPtr, ok := glib.GetCallback(TaskFuncVarPtr); ok { TaskFuncVarRef = cbRefPtr } else { fcb := func(arg0 uintptr, arg1 uintptr, arg2 uintptr, arg3 uintptr) { cbFn := *TaskFuncVar cbFn(arg0, arg1, arg2, arg3) } TaskFuncVarRef = purego.NewCallback(fcb) glib.SaveCallbackWithClosure(TaskFuncVarPtr, TaskFuncVarRef, TaskFuncVar) } } xTaskRunInThreadSync(x.GoPointer(), TaskFuncVarRef) } var xTaskSetCheckCancellable func(uintptr, bool) // Sets or clears @task's check-cancellable flag. If this is %TRUE // (the default), then g_task_propagate_pointer(), etc, and // g_task_had_error() will check the task's #GCancellable first, and // if it has been cancelled, then they will consider the task to have // returned an "Operation was cancelled" error // (%G_IO_ERROR_CANCELLED), regardless of any other error or return // value the task may have had. // // If @check_cancellable is %FALSE, then the #GTask will not check the // cancellable itself, and it is up to @task's owner to do this (eg, // via g_task_return_error_if_cancelled()). // // If you are using g_task_set_return_on_cancel() as well, then // you must leave check-cancellable set %TRUE. func (x *Task) SetCheckCancellable(CheckCancellableVar bool) { xTaskSetCheckCancellable(x.GoPointer(), CheckCancellableVar) } var xTaskSetName func(uintptr, uintptr) // Sets @task’s name, used in debugging and profiling. The name defaults to // %NULL. // // The task name should describe in a human readable way what the task does. // For example, ‘Open file’ or ‘Connect to network host’. It is used to set the // name of the #GSource used for idle completion of the task. // // This function may only be called before the @task is first used in a thread // other than the one it was constructed in. func (x *Task) SetName(NameVar *string) { NameVarPtr := core.GStrdupNullable(NameVar) defer core.GFreeNullable(NameVarPtr) xTaskSetName(x.GoPointer(), NameVarPtr) } var xTaskSetPriority func(uintptr, int) // Sets @task's priority. If you do not call this, it will default to // %G_PRIORITY_DEFAULT. // // This will affect the priority of #GSources created with // g_task_attach_source() and the scheduling of tasks run in threads, // and can also be explicitly retrieved later via // g_task_get_priority(). func (x *Task) SetPriority(PriorityVar int) { xTaskSetPriority(x.GoPointer(), PriorityVar) } var xTaskSetReturnOnCancel func(uintptr, bool) bool // Sets or clears @task's return-on-cancel flag. This is only // meaningful for tasks run via g_task_run_in_thread() or // g_task_run_in_thread_sync(). // // If @return_on_cancel is %TRUE, then cancelling @task's // #GCancellable will immediately cause it to return, as though the // task's #GTaskThreadFunc had called // g_task_return_error_if_cancelled() and then returned. // // This allows you to create a cancellable wrapper around an // uninterruptible function. The #GTaskThreadFunc just needs to be // careful that it does not modify any externally-visible state after // it has been cancelled. To do that, the thread should call // g_task_set_return_on_cancel() again to (atomically) set // return-on-cancel %FALSE before making externally-visible changes; // if the task gets cancelled before the return-on-cancel flag could // be changed, g_task_set_return_on_cancel() will indicate this by // returning %FALSE. // // You can disable and re-enable this flag multiple times if you wish. // If the task's #GCancellable is cancelled while return-on-cancel is // %FALSE, then calling g_task_set_return_on_cancel() to set it %TRUE // again will cause the task to be cancelled at that point. // // If the task's #GCancellable is already cancelled before you call // g_task_run_in_thread()/g_task_run_in_thread_sync(), then the // #GTaskThreadFunc will still be run (for consistency), but the task // will also be completed right away. func (x *Task) SetReturnOnCancel(ReturnOnCancelVar bool) bool { cret := xTaskSetReturnOnCancel(x.GoPointer(), ReturnOnCancelVar) return cret } var xTaskSetSourceTag func(uintptr, uintptr) // Sets @task's source tag. // // You can use this to tag a task return // value with a particular pointer (usually a pointer to the function // doing the tagging) and then later check it using // g_task_get_source_tag() (or g_async_result_is_tagged()) in the // task's "finish" function, to figure out if the response came from a // particular place. // // A macro wrapper around this function will automatically set the // task’s name to the string form of @source_tag if it’s not already // set, for convenience. func (x *Task) SetSourceTag(SourceTagVar uintptr) { xTaskSetSourceTag(x.GoPointer(), SourceTagVar) } var xTaskSetStaticName func(uintptr, uintptr) // Sets @task’s name, used in debugging and profiling. // // This is a variant of g_task_set_name() that avoids copying @name. // // This function is called automatically by [method@Gio.Task.set_source_tag] // unless a name is set. func (x *Task) SetStaticName(NameVar *string) { NameVarPtr := core.GStrdupNullable(NameVar) defer core.GFreeNullable(NameVarPtr) xTaskSetStaticName(x.GoPointer(), NameVarPtr) } var xTaskSetTaskData func(uintptr, uintptr, uintptr) // Sets @task's task data (freeing the existing task data, if any). func (x *Task) SetTaskData(TaskDataVar uintptr, TaskDataDestroyVar *glib.DestroyNotify) { var TaskDataDestroyVarRef uintptr if TaskDataDestroyVar != nil { TaskDataDestroyVarPtr := uintptr(unsafe.Pointer(TaskDataDestroyVar)) if cbRefPtr, ok := glib.GetCallback(TaskDataDestroyVarPtr); ok { TaskDataDestroyVarRef = cbRefPtr } else { fcb := func(arg0 uintptr) { cbFn := *TaskDataDestroyVar cbFn(arg0) } TaskDataDestroyVarRef = purego.NewCallback(fcb) glib.SaveCallbackWithClosure(TaskDataDestroyVarPtr, TaskDataDestroyVarRef, TaskDataDestroyVar) } } xTaskSetTaskData(x.GoPointer(), TaskDataVar, TaskDataDestroyVarRef) } func (c *Task) GoPointer() uintptr { if c == nil { return 0 } return c.Ptr } func (c *Task) SetGoPointer(ptr uintptr) { c.Ptr = ptr } // GetPropertyCompleted gets the "completed" property. // Whether the task has completed, meaning its callback (if set) has been // invoked. // // This can only happen after g_task_return_pointer(), // g_task_return_error() or one of the other return functions have been called // on the task. However, it is not guaranteed to happen immediately after // those functions are called, as the task’s callback may need to be scheduled // to run in a different thread. // // That means it is **not safe** to use this property to track whether a // return function has been called on the #GTask. Callers must do that // tracking themselves, typically by linking the lifetime of the #GTask to the // control flow of their code. // // This property is guaranteed to change from %FALSE to %TRUE exactly once. // // The #GObject::notify signal for this change is emitted in the same main // context as the task’s callback, immediately after that callback is invoked. func (x *Task) GetPropertyCompleted() bool { var v gobject.Value x.GetProperty("completed", &v) return v.GetBoolean() } // Gets the user data from a [iface@Gio.AsyncResult]. func (x *Task) GetUserData() uintptr { cret := XGAsyncResultGetUserData(x.GoPointer()) return cret } // Checks if @res has the given @source_tag (generally a function // pointer indicating the function @res was created by). func (x *Task) IsTagged(SourceTagVar uintptr) bool { cret := XGAsyncResultIsTagged(x.GoPointer(), SourceTagVar) return cret } // If @res is a [class@Gio.SimpleAsyncResult], this is equivalent to // [method@Gio.SimpleAsyncResult.propagate_error]. Otherwise it returns // `FALSE`. // // This can be used for legacy error handling in async `*_finish()` // wrapper functions that traditionally handled [class@Gio.SimpleAsyncResult] // error returns themselves rather than calling into the virtual method. // This should not be used in new code; [iface@Gio.AsyncResult] errors that are // set by virtual methods should also be extracted by virtual methods, // to enable subclasses to chain up correctly. func (x *Task) LegacyPropagateError() (bool, error) { var cerr *glib.Error cret := XGAsyncResultLegacyPropagateError(x.GoPointer()) if cerr == nil { return cret, nil } return cret, cerr } var xTaskIsValid func(uintptr, uintptr) bool // Checks that @result is a #GTask, and that @source_object is its // source object (or that @source_object is %NULL and @result has no // source object). This can be used in g_return_if_fail() checks. func TaskIsValid(ResultVar AsyncResult, SourceObjectVar *gobject.Object) bool { cret := xTaskIsValid(ResultVar.GoPointer(), SourceObjectVar.GoPointer()) return cret } var xTaskReportError func(uintptr, uintptr, uintptr, uintptr, *glib.Error) // Creates a #GTask and then immediately calls g_task_return_error() // on it. Use this in the wrapper function of an asynchronous method // when you want to avoid even calling the virtual method. You can // then use g_async_result_is_tagged() in the finish method wrapper to // check if the result there is tagged as having been created by the // wrapper method, and deal with it appropriately if so. // // See also g_task_report_new_error(). func TaskReportError(SourceObjectVar *gobject.Object, CallbackVar *AsyncReadyCallback, CallbackDataVar uintptr, SourceTagVar uintptr, ErrorVar *glib.Error) { var CallbackVarRef uintptr if CallbackVar != nil { CallbackVarPtr := uintptr(unsafe.Pointer(CallbackVar)) if cbRefPtr, ok := glib.GetCallback(CallbackVarPtr); ok { CallbackVarRef = cbRefPtr } else { fcb := func(arg0 uintptr, arg1 uintptr, arg2 uintptr) { cbFn := *CallbackVar cbFn(arg0, arg1, arg2) } CallbackVarRef = purego.NewCallback(fcb) glib.SaveCallbackWithClosure(CallbackVarPtr, CallbackVarRef, CallbackVar) } } xTaskReportError(SourceObjectVar.GoPointer(), CallbackVarRef, CallbackDataVar, SourceTagVar, ErrorVar) } var xTaskReportNewError func(uintptr, uintptr, uintptr, uintptr, glib.Quark, int, string, ...interface{}) // Creates a #GTask and then immediately calls // g_task_return_new_error() on it. Use this in the wrapper function // of an asynchronous method when you want to avoid even calling the // virtual method. You can then use g_async_result_is_tagged() in the // finish method wrapper to check if the result there is tagged as // having been created by the wrapper method, and deal with it // appropriately if so. // // See also g_task_report_error(). func TaskReportNewError(SourceObjectVar *gobject.Object, CallbackVar *AsyncReadyCallback, CallbackDataVar uintptr, SourceTagVar uintptr, DomainVar glib.Quark, CodeVar int, FormatVar string, varArgs ...interface{}) { var CallbackVarRef uintptr if CallbackVar != nil { CallbackVarPtr := uintptr(unsafe.Pointer(CallbackVar)) if cbRefPtr, ok := glib.GetCallback(CallbackVarPtr); ok { CallbackVarRef = cbRefPtr } else { fcb := func(arg0 uintptr, arg1 uintptr, arg2 uintptr) { cbFn := *CallbackVar cbFn(arg0, arg1, arg2) } CallbackVarRef = purego.NewCallback(fcb) glib.SaveCallbackWithClosure(CallbackVarPtr, CallbackVarRef, CallbackVar) } } xTaskReportNewError(SourceObjectVar.GoPointer(), CallbackVarRef, CallbackDataVar, SourceTagVar, DomainVar, CodeVar, FormatVar, varArgs...) } func init() { core.SetPackageName("GIO", "gio-2.0") core.SetSharedLibraries("GIO", []string{"libgio-2.0.so.0"}) var libs []uintptr for _, libPath := range core.GetPaths("GIO") { lib, err := purego.Dlopen(libPath, purego.RTLD_NOW|purego.RTLD_GLOBAL) if err != nil { panic(err) } libs = append(libs, lib) } core.PuregoSafeRegister(&xTaskGLibType, libs, "g_task_get_type") core.PuregoSafeRegister(&xNewTask, libs, "g_task_new") core.PuregoSafeRegister(&xTaskAttachSource, libs, "g_task_attach_source") core.PuregoSafeRegister(&xTaskGetCancellable, libs, "g_task_get_cancellable") core.PuregoSafeRegister(&xTaskGetCheckCancellable, libs, "g_task_get_check_cancellable") core.PuregoSafeRegister(&xTaskGetCompleted, libs, "g_task_get_completed") core.PuregoSafeRegister(&xTaskGetContext, libs, "g_task_get_context") core.PuregoSafeRegister(&xTaskGetName, libs, "g_task_get_name") core.PuregoSafeRegister(&xTaskGetPriority, libs, "g_task_get_priority") core.PuregoSafeRegister(&xTaskGetReturnOnCancel, libs, "g_task_get_return_on_cancel") core.PuregoSafeRegister(&xTaskGetSourceObject, libs, "g_task_get_source_object") core.PuregoSafeRegister(&xTaskGetSourceTag, libs, "g_task_get_source_tag") core.PuregoSafeRegister(&xTaskGetTaskData, libs, "g_task_get_task_data") core.PuregoSafeRegister(&xTaskHadError, libs, "g_task_had_error") core.PuregoSafeRegister(&xTaskPropagateBoolean, libs, "g_task_propagate_boolean") core.PuregoSafeRegister(&xTaskPropagateInt, libs, "g_task_propagate_int") core.PuregoSafeRegister(&xTaskPropagatePointer, libs, "g_task_propagate_pointer") core.PuregoSafeRegister(&xTaskPropagateValue, libs, "g_task_propagate_value") core.PuregoSafeRegister(&xTaskReturnBoolean, libs, "g_task_return_boolean") core.PuregoSafeRegister(&xTaskReturnError, libs, "g_task_return_error") core.PuregoSafeRegister(&xTaskReturnErrorIfCancelled, libs, "g_task_return_error_if_cancelled") core.PuregoSafeRegister(&xTaskReturnInt, libs, "g_task_return_int") core.PuregoSafeRegister(&xTaskReturnNewError, libs, "g_task_return_new_error") core.PuregoSafeRegister(&xTaskReturnNewErrorLiteral, libs, "g_task_return_new_error_literal") core.PuregoSafeRegister(&xTaskReturnPointer, libs, "g_task_return_pointer") core.PuregoSafeRegister(&xTaskReturnPrefixedError, libs, "g_task_return_prefixed_error") core.PuregoSafeRegister(&xTaskReturnValue, libs, "g_task_return_value") core.PuregoSafeRegister(&xTaskRunInThread, libs, "g_task_run_in_thread") core.PuregoSafeRegister(&xTaskRunInThreadSync, libs, "g_task_run_in_thread_sync") core.PuregoSafeRegister(&xTaskSetCheckCancellable, libs, "g_task_set_check_cancellable") core.PuregoSafeRegister(&xTaskSetName, libs, "g_task_set_name") core.PuregoSafeRegister(&xTaskSetPriority, libs, "g_task_set_priority") core.PuregoSafeRegister(&xTaskSetReturnOnCancel, libs, "g_task_set_return_on_cancel") core.PuregoSafeRegister(&xTaskSetSourceTag, libs, "g_task_set_source_tag") core.PuregoSafeRegister(&xTaskSetStaticName, libs, "g_task_set_static_name") core.PuregoSafeRegister(&xTaskSetTaskData, libs, "g_task_set_task_data") core.PuregoSafeRegister(&xTaskIsValid, libs, "g_task_is_valid") core.PuregoSafeRegister(&xTaskReportError, libs, "g_task_report_error") core.PuregoSafeRegister(&xTaskReportNewError, libs, "g_task_report_new_error") }