mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 03:16:17 +01:00
Merge branch 'migrate-to-gi-docgen10' into 'main'
Switch to using gi-docgen for docs (batch 10) See merge request GNOME/glib!3709
This commit is contained in:
commit
09b728b2da
79
docs/reference/gio/dbus-error.md
Normal file
79
docs/reference/gio/dbus-error.md
Normal file
@ -0,0 +1,79 @@
|
||||
Title: D-Bus Error Handling
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
SPDX-FileCopyrightText: 2010 David Zeuthen
|
||||
SPDX-FileCopyrightText: 2012 Aleksander Morgado
|
||||
|
||||
# D-Bus Error Handling
|
||||
|
||||
All facilities that return errors from remote methods (such as
|
||||
[method@Gio.DBusConnection.call_sync]) use [type@GLib.Error] to represent both
|
||||
D-Bus errors (e.g. errors returned from the other peer) and locally in-process
|
||||
generated errors.
|
||||
|
||||
To check if a returned [type@GLib.Error] is an error from a remote peer, use
|
||||
[func@Gio.DBusError.is_remote_error]. To get the actual D-Bus error name,
|
||||
use [func@Gio.DBusError.get_remote_error]. Before presenting an error, always
|
||||
use [func@Gio.DBusError.strip_remote_error].
|
||||
|
||||
In addition, facilities used to return errors to a remote peer also use
|
||||
[type@GLib.Error]. See [method@Gio.DBusMethodInvocation.return_error] for
|
||||
discussion about how the D-Bus error name is set.
|
||||
|
||||
Applications can associate a [type@GLib.Error] error domain with a set of D-Bus
|
||||
errors in order to automatically map from D-Bus errors to [type@GLib.Error] and
|
||||
back. This is typically done in the function returning the [type@GLib.Quark] for
|
||||
the error domain:
|
||||
|
||||
```c
|
||||
// foo-bar-error.h:
|
||||
|
||||
#define FOO_BAR_ERROR (foo_bar_error_quark ())
|
||||
GQuark foo_bar_error_quark (void);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FOO_BAR_ERROR_FAILED,
|
||||
FOO_BAR_ERROR_ANOTHER_ERROR,
|
||||
FOO_BAR_ERROR_SOME_THIRD_ERROR,
|
||||
FOO_BAR_N_ERRORS / *< skip >* /
|
||||
} FooBarError;
|
||||
|
||||
// foo-bar-error.c:
|
||||
|
||||
static const GDBusErrorEntry foo_bar_error_entries[] =
|
||||
{
|
||||
{FOO_BAR_ERROR_FAILED, "org.project.Foo.Bar.Error.Failed"},
|
||||
{FOO_BAR_ERROR_ANOTHER_ERROR, "org.project.Foo.Bar.Error.AnotherError"},
|
||||
{FOO_BAR_ERROR_SOME_THIRD_ERROR, "org.project.Foo.Bar.Error.SomeThirdError"},
|
||||
};
|
||||
|
||||
// Ensure that every error code has an associated D-Bus error name
|
||||
G_STATIC_ASSERT (G_N_ELEMENTS (foo_bar_error_entries) == FOO_BAR_N_ERRORS);
|
||||
|
||||
GQuark
|
||||
foo_bar_error_quark (void)
|
||||
{
|
||||
static gsize quark = 0;
|
||||
g_dbus_error_register_error_domain ("foo-bar-error-quark",
|
||||
&quark,
|
||||
foo_bar_error_entries,
|
||||
G_N_ELEMENTS (foo_bar_error_entries));
|
||||
return (GQuark) quark;
|
||||
}
|
||||
```
|
||||
|
||||
With this setup, a D-Bus peer can transparently pass e.g.
|
||||
`FOO_BAR_ERROR_ANOTHER_ERROR` and other peers will see the D-Bus error name
|
||||
`org.project.Foo.Bar.Error.AnotherError`.
|
||||
|
||||
If the other peer is using GDBus, and has registered the association with
|
||||
[func@Gio.DBusError.register_error_domain] in advance (e.g. by invoking the
|
||||
`FOO_BAR_ERROR` quark generation itself in the previous example) the peer will
|
||||
see also `FOO_BAR_ERROR_ANOTHER_ERROR` instead of `G_IO_ERROR_DBUS_ERROR`. Note
|
||||
that GDBus clients can still recover `org.project.Foo.Bar.Error.AnotherError`
|
||||
using [func@Gio.DBusError.get_remote_error].
|
||||
|
||||
Note that the `G_DBUS_ERROR` error domain is intended only for returning errors
|
||||
from a remote message bus process. Errors generated locally in-process by e.g.
|
||||
[class@Gio.DBusConnection] should use the `G_IO_ERROR` domain.
|
||||
|
23
docs/reference/gio/dbus-introspection.md
Normal file
23
docs/reference/gio/dbus-introspection.md
Normal file
@ -0,0 +1,23 @@
|
||||
Title: D-Bus Introspection Data
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
SPDX-FileCopyrightText: 2010 David Zeuthen
|
||||
SPDX-FileCopyrightText: 2010 Matthias Clasen
|
||||
|
||||
# D-Bus Introspection Data
|
||||
|
||||
Various data structures and convenience routines to parse and
|
||||
generate D-Bus introspection XML. Introspection information is
|
||||
used when registering objects with [method@Gio.DBusConnection.register_object].
|
||||
|
||||
The format of D-Bus introspection XML is specified in the
|
||||
[D-Bus specification](http://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format).
|
||||
|
||||
The main introspection data structures are:
|
||||
* [type@Gio.DBusNodeInfo]
|
||||
* [type@Gio.DBusInterfaceInfo]
|
||||
* [type@Gio.DBusPropertyInfo]
|
||||
* [type@Gio.DBusMethodInfo]
|
||||
* [type@Gio.DBusSignalInfo]
|
||||
* [type@Gio.DBusArgInfo]
|
||||
* [type@Gio.DBusAnnotationInfo]
|
||||
|
14
docs/reference/gio/dbus-name-owning.md
Normal file
14
docs/reference/gio/dbus-name-owning.md
Normal file
@ -0,0 +1,14 @@
|
||||
Title: D-Bus Name Owning
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
SPDX-FileCopyrightText: 2010 David Zeuthen
|
||||
|
||||
# D-Bus Name Owning
|
||||
|
||||
Convenience API for owning bus names.
|
||||
|
||||
A simple example for owning a name can be found in
|
||||
[`gdbus-example-own-name.c`](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-example-own-name.c).
|
||||
|
||||
The main API for owning names is:
|
||||
* [func@Gio.bus_own_name]
|
||||
* [func@Gio.bus_unown_name]
|
14
docs/reference/gio/dbus-name-watching.md
Normal file
14
docs/reference/gio/dbus-name-watching.md
Normal file
@ -0,0 +1,14 @@
|
||||
Title: D-Bus Name Watching
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
SPDX-FileCopyrightText: 2010 David Zeuthen
|
||||
|
||||
# D-Bus Name Watching
|
||||
|
||||
Convenience API for watching bus names.
|
||||
|
||||
A simple example for watching a name can be found in
|
||||
[`gdbus-example-watch-name.c`](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-example-watch-name.c).
|
||||
|
||||
The main API for watching names is:
|
||||
* [func@Gio.bus_watch_name]
|
||||
* [func@Gio.bus_unwatch_name]
|
28
docs/reference/gio/dbus-utils.md
Normal file
28
docs/reference/gio/dbus-utils.md
Normal file
@ -0,0 +1,28 @@
|
||||
Title: D-Bus Utilities
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
SPDX-FileCopyrightText: 2010 David Zeuthen
|
||||
|
||||
# D-Bus Utilities
|
||||
|
||||
Various utility routines related to D-Bus.
|
||||
|
||||
GUID support:
|
||||
* [func@Gio.dbus_is_guid]
|
||||
* [func@Gio.dbus_generate_guid]
|
||||
|
||||
Name validation:
|
||||
* [func@Gio.dbus_is_name]
|
||||
* [func@Gio.dbus_is_unique_name]
|
||||
* [func@Gio.dbus_is_member_name]
|
||||
* [func@Gio.dbus_is_interface_name]
|
||||
* [func@Gio.dbus_is_error_name]
|
||||
|
||||
Conversion between [type@GLib.Variant] and [type@GObject.Value]:
|
||||
* [func@Gio.dbus_gvariant_to_gvalue]
|
||||
* [func@Gio.dbus_gvalue_to_gvariant]
|
||||
|
||||
Path escaping:
|
||||
* [func@Gio.dbus_escape_object_path_bytestring]
|
||||
* [func@Gio.dbus_escape_object_path]
|
||||
* [func@Gio.dbus_unescape_object_path]
|
||||
|
12
docs/reference/gio/error.md
Normal file
12
docs/reference/gio/error.md
Normal file
@ -0,0 +1,12 @@
|
||||
Title: GIOError
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
SPDX-FileCopyrightText: 2007 A. Walton
|
||||
|
||||
# GIOError
|
||||
|
||||
Contains helper functions for reporting errors to the user.
|
||||
|
||||
Functions for converting between different error reporting mechanisms:
|
||||
* [func@Gio.io_error_from_errno]
|
||||
* [func@Gio.io_error_from_file_error]
|
||||
|
@ -44,6 +44,14 @@ content_files = [
|
||||
"file-attributes.md",
|
||||
"tls-overview.md",
|
||||
|
||||
"error.md",
|
||||
|
||||
"dbus-error.md",
|
||||
"dbus-introspection.md",
|
||||
"dbus-name-owning.md",
|
||||
"dbus-name-watching.md",
|
||||
"dbus-utils.md",
|
||||
|
||||
"migrating-gdbus.md",
|
||||
"migrating-gconf.md",
|
||||
"migrating-gnome-vfs.md",
|
||||
|
@ -225,6 +225,12 @@ endif
|
||||
|
||||
# gi-docgen version
|
||||
expand_content_files = [
|
||||
'dbus-error.md',
|
||||
'dbus-introspection.md',
|
||||
'dbus-name-owning.md',
|
||||
'dbus-name-watching.md',
|
||||
'dbus-utils.md',
|
||||
'error.md',
|
||||
'file-attributes.md',
|
||||
'migrating-gconf.md',
|
||||
'migrating-gdbus.md',
|
||||
|
@ -33,82 +33,6 @@
|
||||
|
||||
#include "glibintl.h"
|
||||
|
||||
/**
|
||||
* SECTION:gdbuserror
|
||||
* @title: GDBusError
|
||||
* @short_description: Mapping D-Bus errors to and from GError
|
||||
* @include: gio/gio.h
|
||||
*
|
||||
* All facilities that return errors from remote methods (such as
|
||||
* g_dbus_connection_call_sync()) use #GError to represent both D-Bus
|
||||
* errors (e.g. errors returned from the other peer) and locally
|
||||
* in-process generated errors.
|
||||
*
|
||||
* To check if a returned #GError is an error from a remote peer, use
|
||||
* g_dbus_error_is_remote_error(). To get the actual D-Bus error name,
|
||||
* use g_dbus_error_get_remote_error(). Before presenting an error,
|
||||
* always use g_dbus_error_strip_remote_error().
|
||||
*
|
||||
* In addition, facilities used to return errors to a remote peer also
|
||||
* use #GError. See g_dbus_method_invocation_return_error() for
|
||||
* discussion about how the D-Bus error name is set.
|
||||
*
|
||||
* Applications can associate a #GError error domain with a set of D-Bus errors in order to
|
||||
* automatically map from D-Bus errors to #GError and back. This
|
||||
* is typically done in the function returning the #GQuark for the
|
||||
* error domain:
|
||||
* |[<!-- language="C" -->
|
||||
* // foo-bar-error.h:
|
||||
*
|
||||
* #define FOO_BAR_ERROR (foo_bar_error_quark ())
|
||||
* GQuark foo_bar_error_quark (void);
|
||||
*
|
||||
* typedef enum
|
||||
* {
|
||||
* FOO_BAR_ERROR_FAILED,
|
||||
* FOO_BAR_ERROR_ANOTHER_ERROR,
|
||||
* FOO_BAR_ERROR_SOME_THIRD_ERROR,
|
||||
* FOO_BAR_N_ERRORS / *< skip >* /
|
||||
* } FooBarError;
|
||||
*
|
||||
* // foo-bar-error.c:
|
||||
*
|
||||
* static const GDBusErrorEntry foo_bar_error_entries[] =
|
||||
* {
|
||||
* {FOO_BAR_ERROR_FAILED, "org.project.Foo.Bar.Error.Failed"},
|
||||
* {FOO_BAR_ERROR_ANOTHER_ERROR, "org.project.Foo.Bar.Error.AnotherError"},
|
||||
* {FOO_BAR_ERROR_SOME_THIRD_ERROR, "org.project.Foo.Bar.Error.SomeThirdError"},
|
||||
* };
|
||||
*
|
||||
* // Ensure that every error code has an associated D-Bus error name
|
||||
* G_STATIC_ASSERT (G_N_ELEMENTS (foo_bar_error_entries) == FOO_BAR_N_ERRORS);
|
||||
*
|
||||
* GQuark
|
||||
* foo_bar_error_quark (void)
|
||||
* {
|
||||
* static gsize quark = 0;
|
||||
* g_dbus_error_register_error_domain ("foo-bar-error-quark",
|
||||
* &quark,
|
||||
* foo_bar_error_entries,
|
||||
* G_N_ELEMENTS (foo_bar_error_entries));
|
||||
* return (GQuark) quark;
|
||||
* }
|
||||
* ]|
|
||||
* With this setup, a D-Bus peer can transparently pass e.g. %FOO_BAR_ERROR_ANOTHER_ERROR and
|
||||
* other peers will see the D-Bus error name org.project.Foo.Bar.Error.AnotherError.
|
||||
*
|
||||
* If the other peer is using GDBus, and has registered the association with
|
||||
* g_dbus_error_register_error_domain() in advance (e.g. by invoking the %FOO_BAR_ERROR quark
|
||||
* generation itself in the previous example) the peer will see also %FOO_BAR_ERROR_ANOTHER_ERROR instead
|
||||
* of %G_IO_ERROR_DBUS_ERROR. Note that GDBus clients can still recover
|
||||
* org.project.Foo.Bar.Error.AnotherError using g_dbus_error_get_remote_error().
|
||||
*
|
||||
* Note that the %G_DBUS_ERROR error domain is intended only
|
||||
* for returning errors from a remote message bus process. Errors
|
||||
* generated locally in-process by e.g. #GDBusConnection should use the
|
||||
* %G_IO_ERROR domain.
|
||||
*/
|
||||
|
||||
static const GDBusErrorEntry g_dbus_error_entries[] =
|
||||
{
|
||||
{G_DBUS_ERROR_FAILED, "org.freedesktop.DBus.Error.Failed"},
|
||||
|
@ -29,20 +29,6 @@
|
||||
|
||||
#include "glibintl.h"
|
||||
|
||||
/**
|
||||
* SECTION:gdbusintrospection
|
||||
* @title: D-Bus Introspection Data
|
||||
* @short_description: Node and interface description data structures
|
||||
* @include: gio/gio.h
|
||||
*
|
||||
* Various data structures and convenience routines to parse and
|
||||
* generate D-Bus introspection XML. Introspection information is
|
||||
* used when registering objects with g_dbus_connection_register_object().
|
||||
*
|
||||
* The format of D-Bus introspection XML is specified in the
|
||||
* [D-Bus specification](http://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format)
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
#define _MY_DEFINE_BOXED_TYPE(TypeName, type_name) \
|
||||
|
@ -28,23 +28,12 @@
|
||||
|
||||
/* Prelude {{{1 */
|
||||
|
||||
/**
|
||||
* SECTION:gdbusmenumodel
|
||||
* @title: GDBusMenuModel
|
||||
* @short_description: A D-Bus GMenuModel implementation
|
||||
* @include: gio/gio.h
|
||||
* @see_also: [GMenuModel Exporter][gio-GMenuModel-exporter]
|
||||
*
|
||||
* #GDBusMenuModel is an implementation of #GMenuModel that can be used
|
||||
* as a proxy for a menu model that is exported over D-Bus with
|
||||
* g_dbus_connection_export_menu_model().
|
||||
*/
|
||||
|
||||
/**
|
||||
* GDBusMenuModel:
|
||||
*
|
||||
* #GDBusMenuModel is an opaque data structure and can only be accessed
|
||||
* using the following functions.
|
||||
* `GDBusMenuModel` is an implementation of [class@Gio.MenuModel] that can be
|
||||
* used as a proxy for a menu model that is exported over D-Bus with
|
||||
* [method@Gio.DBusConnection.export_menu_model].
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -32,18 +32,6 @@
|
||||
|
||||
#include "glibintl.h"
|
||||
|
||||
/**
|
||||
* SECTION:gdbusnameowning
|
||||
* @title: Owning Bus Names
|
||||
* @short_description: Simple API for owning bus names
|
||||
* @include: gio/gio.h
|
||||
*
|
||||
* Convenience API for owning bus names.
|
||||
*
|
||||
* A simple example for owning a name can be found in
|
||||
* [gdbus-example-own-name.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-example-own-name.c)
|
||||
*/
|
||||
|
||||
G_LOCK_DEFINE_STATIC (lock);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
@ -33,18 +33,6 @@
|
||||
|
||||
#include "glibintl.h"
|
||||
|
||||
/**
|
||||
* SECTION:gdbusnamewatching
|
||||
* @title: Watching Bus Names
|
||||
* @short_description: Simple API for watching bus names
|
||||
* @include: gio/gio.h
|
||||
*
|
||||
* Convenience API for watching bus names.
|
||||
*
|
||||
* A simple example for watching a name can be found in
|
||||
* [gdbus-example-watch-name.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-example-watch-name.c)
|
||||
*/
|
||||
|
||||
G_LOCK_DEFINE_STATIC (lock);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
@ -30,25 +30,16 @@
|
||||
#include "glibintl.h"
|
||||
#include "gmarshal-internal.h"
|
||||
|
||||
/**
|
||||
* SECTION:gdbusobjectmanager
|
||||
* @short_description: Base type for D-Bus object managers
|
||||
* @include: gio/gio.h
|
||||
*
|
||||
* The #GDBusObjectManager type is the base type for service- and
|
||||
* client-side implementations of the standardized
|
||||
* [org.freedesktop.DBus.ObjectManager](http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager)
|
||||
* interface.
|
||||
*
|
||||
* See #GDBusObjectManagerClient for the client-side implementation
|
||||
* and #GDBusObjectManagerServer for the service-side implementation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* GDBusObjectManager:
|
||||
*
|
||||
* #GDBusObjectManager is an opaque data structure and can only be accessed
|
||||
* using the following functions.
|
||||
* The `GDBusObjectManager` type is the base type for service- and
|
||||
* client-side implementations of the standardized
|
||||
* [`org.freedesktop.DBus.ObjectManager`](http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager)
|
||||
* interface.
|
||||
*
|
||||
* See [class@Gio.DBusObjectManagerClient] for the client-side implementation
|
||||
* and [class@Gio.DBusObjectManagerServer] for the service-side implementation.
|
||||
*/
|
||||
|
||||
typedef GDBusObjectManagerIface GDBusObjectManagerInterface;
|
||||
|
@ -37,13 +37,11 @@
|
||||
#include "glibintl.h"
|
||||
|
||||
/**
|
||||
* SECTION:gdbusobjectmanagerserver
|
||||
* @short_description: Service-side object manager
|
||||
* @include: gio/gio.h
|
||||
* GDBusObjectManagerServer:
|
||||
*
|
||||
* #GDBusObjectManagerServer is used to export #GDBusObject instances using
|
||||
* the standardized
|
||||
* [org.freedesktop.DBus.ObjectManager](http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager)
|
||||
* `GDBusObjectManagerServer` is used to export [iface@Gio.DBusObject] instances
|
||||
* using the standardized
|
||||
* [`org.freedesktop.DBus.ObjectManager`](http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager)
|
||||
* interface. For example, remote D-Bus clients can get all objects
|
||||
* and properties in a single call. Additionally, any change in the
|
||||
* object hierarchy is broadcast using signals. This means that D-Bus
|
||||
@ -59,10 +57,11 @@
|
||||
* It is supported, but not recommended, to export an object manager at the root
|
||||
* path, `/`.
|
||||
*
|
||||
* See #GDBusObjectManagerClient for the client-side code that is
|
||||
* intended to be used with #GDBusObjectManagerServer or any D-Bus
|
||||
* object implementing the org.freedesktop.DBus.ObjectManager
|
||||
* interface.
|
||||
* See [class@Gio.DBusObjectManagerClient] for the client-side code that is
|
||||
* intended to be used with `GDBusObjectManagerServer` or any D-Bus
|
||||
* object implementing the `org.freedesktop.DBus.ObjectManager` interface.
|
||||
*
|
||||
* Since: 2.30
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
|
@ -37,14 +37,6 @@ G_BEGIN_DECLS
|
||||
typedef struct _GDBusObjectManagerServerClass GDBusObjectManagerServerClass;
|
||||
typedef struct _GDBusObjectManagerServerPrivate GDBusObjectManagerServerPrivate;
|
||||
|
||||
/**
|
||||
* GDBusObjectManagerServer:
|
||||
*
|
||||
* The #GDBusObjectManagerServer structure contains private data and should
|
||||
* only be accessed using the provided API.
|
||||
*
|
||||
* Since: 2.30
|
||||
*/
|
||||
struct _GDBusObjectManagerServer
|
||||
{
|
||||
/*< private >*/
|
||||
|
@ -34,15 +34,15 @@
|
||||
#include "glibintl.h"
|
||||
|
||||
/**
|
||||
* SECTION:gdbusobjectskeleton
|
||||
* @short_description: Service-side D-Bus object
|
||||
* @include: gio/gio.h
|
||||
* GDBusObjectSkeleton:
|
||||
*
|
||||
* A #GDBusObjectSkeleton instance is essentially a group of D-Bus
|
||||
* A `GDBusObjectSkeleton` instance is essentially a group of D-Bus
|
||||
* interfaces. The set of exported interfaces on the object may be
|
||||
* dynamic and change at runtime.
|
||||
*
|
||||
* This type is intended to be used with #GDBusObjectManager.
|
||||
* This type is intended to be used with [iface@Gio.DBusObjectManager].
|
||||
*
|
||||
* Since: 2.30
|
||||
*/
|
||||
|
||||
struct _GDBusObjectSkeletonPrivate
|
||||
|
@ -37,14 +37,6 @@ G_BEGIN_DECLS
|
||||
typedef struct _GDBusObjectSkeletonClass GDBusObjectSkeletonClass;
|
||||
typedef struct _GDBusObjectSkeletonPrivate GDBusObjectSkeletonPrivate;
|
||||
|
||||
/**
|
||||
* GDBusObjectSkeleton:
|
||||
*
|
||||
* The #GDBusObjectSkeleton structure contains private data and should only be
|
||||
* accessed using the provided API.
|
||||
*
|
||||
* Since: 2.30
|
||||
*/
|
||||
struct _GDBusObjectSkeleton
|
||||
{
|
||||
/*< private >*/
|
||||
|
@ -47,54 +47,56 @@
|
||||
#include "gmarshal-internal.h"
|
||||
|
||||
/**
|
||||
* SECTION:gdbusproxy
|
||||
* @short_description: Client-side D-Bus interface proxy
|
||||
* @include: gio/gio.h
|
||||
* GDBusProxy:
|
||||
*
|
||||
* #GDBusProxy is a base class used for proxies to access a D-Bus
|
||||
* interface on a remote object. A #GDBusProxy can be constructed for
|
||||
* `GDBusProxy` is a base class used for proxies to access a D-Bus
|
||||
* interface on a remote object. A `GDBusProxy` can be constructed for
|
||||
* both well-known and unique names.
|
||||
*
|
||||
* By default, #GDBusProxy will cache all properties (and listen to
|
||||
* By default, `GDBusProxy` will cache all properties (and listen to
|
||||
* changes) of the remote object, and proxy all signals that get
|
||||
* emitted. This behaviour can be changed by passing suitable
|
||||
* #GDBusProxyFlags when the proxy is created. If the proxy is for a
|
||||
* [flags@Gio.DBusProxyFlags] when the proxy is created. If the proxy is for a
|
||||
* well-known name, the property cache is flushed when the name owner
|
||||
* vanishes and reloaded when a name owner appears.
|
||||
*
|
||||
* The unique name owner of the proxy's name is tracked and can be read from
|
||||
* #GDBusProxy:g-name-owner. Connect to the #GObject::notify signal to
|
||||
* get notified of changes. Additionally, only signals and property
|
||||
* changes emitted from the current name owner are considered and
|
||||
* calls are always sent to the current name owner. This avoids a
|
||||
* number of race conditions when the name is lost by one owner and
|
||||
* claimed by another. However, if no name owner currently exists,
|
||||
* The unique name owner of the proxy’s name is tracked and can be read from
|
||||
* [property@Gio.DBusProxy:g-name-owner]. Connect to the
|
||||
* [signal@GObject.Object::notify] signal to get notified of changes.
|
||||
* Additionally, only signals and property changes emitted from the current name
|
||||
* owner are considered and calls are always sent to the current name owner.
|
||||
* This avoids a number of race conditions when the name is lost by one owner
|
||||
* and claimed by another. However, if no name owner currently exists,
|
||||
* then calls will be sent to the well-known name which may result in
|
||||
* the message bus launching an owner (unless
|
||||
* %G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START is set).
|
||||
* `G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START` is set).
|
||||
*
|
||||
* If the proxy is for a stateless D-Bus service, where the name owner may
|
||||
* be started and stopped between calls, the #GDBusProxy:g-name-owner tracking
|
||||
* of #GDBusProxy will cause the proxy to drop signal and property changes from
|
||||
* the service after it has restarted for the first time. When interacting
|
||||
* with a stateless D-Bus service, do not use #GDBusProxy — use direct D-Bus
|
||||
* method calls and signal connections.
|
||||
* be started and stopped between calls, the
|
||||
* [property@Gio.DBusProxy:g-name-owner] tracking of `GDBusProxy` will cause the
|
||||
* proxy to drop signal and property changes from the service after it has
|
||||
* restarted for the first time. When interacting with a stateless D-Bus
|
||||
* service, do not use `GDBusProxy` — use direct D-Bus method calls and signal
|
||||
* connections.
|
||||
*
|
||||
* The generic #GDBusProxy::g-properties-changed and
|
||||
* #GDBusProxy::g-signal signals are not very convenient to work with.
|
||||
* Therefore, the recommended way of working with proxies is to subclass
|
||||
* #GDBusProxy, and have more natural properties and signals in your derived
|
||||
* class. This [example][gdbus-example-gdbus-codegen] shows how this can
|
||||
* easily be done using the [gdbus-codegen][gdbus-codegen] tool.
|
||||
* The generic [signal@Gio.DBusProxy::g-properties-changed] and
|
||||
* [signal@Gio.DBusProxy::g-signal] signals are not very convenient to work
|
||||
* with. Therefore, the recommended way of working with proxies is to subclass
|
||||
* `GDBusProxy`, and have more natural properties and signals in your derived
|
||||
* class. This [example](migrating-gdbus.html#using-gdbus-codegen) shows how
|
||||
* this can easily be done using the [`gdbus-codegen`](gdbus-codegen.html) tool.
|
||||
*
|
||||
* A #GDBusProxy instance can be used from multiple threads but note
|
||||
* that all signals (e.g. #GDBusProxy::g-signal, #GDBusProxy::g-properties-changed
|
||||
* and #GObject::notify) are emitted in the
|
||||
* [thread-default main context][g-main-context-push-thread-default]
|
||||
* of the thread where the instance was constructed.
|
||||
* A `GDBusProxy` instance can be used from multiple threads but note
|
||||
* that all signals (e.g. [signal@Gio.DBusProxy::g-signal],
|
||||
* [signal@Gio.DBusProxy::g-properties-changed] and
|
||||
* [signal@GObject.Object::notify]) are emitted in the thread-default main
|
||||
* context (see [method@GLib.MainContext.push_thread_default]) of the thread
|
||||
* where the instance was constructed.
|
||||
*
|
||||
* An example using a proxy for a well-known name can be found in
|
||||
* [gdbus-example-watch-proxy.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-example-watch-proxy.c)
|
||||
* [`gdbus-example-watch-proxy.c`](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-example-watch-proxy.c).
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
|
||||
/* lock protecting the mutable properties: name_owner, timeout_msec,
|
||||
|
@ -42,14 +42,6 @@ G_BEGIN_DECLS
|
||||
typedef struct _GDBusProxyClass GDBusProxyClass;
|
||||
typedef struct _GDBusProxyPrivate GDBusProxyPrivate;
|
||||
|
||||
/**
|
||||
* GDBusProxy:
|
||||
*
|
||||
* The #GDBusProxy structure contains only private data and
|
||||
* should only be accessed using the provided API.
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
struct _GDBusProxy
|
||||
{
|
||||
/*< private >*/
|
||||
|
@ -29,15 +29,6 @@
|
||||
|
||||
#include "glibintl.h"
|
||||
|
||||
/**
|
||||
* SECTION:gdbusutils
|
||||
* @title: D-Bus Utilities
|
||||
* @short_description: Various utilities related to D-Bus
|
||||
* @include: gio/gio.h
|
||||
*
|
||||
* Various utility routines related to D-Bus.
|
||||
*/
|
||||
|
||||
static gboolean
|
||||
is_valid_bus_name_character (gint c,
|
||||
gboolean allow_hyphen)
|
||||
|
127
gio/gfile.c
127
gio/gfile.c
@ -86,94 +86,99 @@ typedef off_t loff_t;
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:gfile
|
||||
* @short_description: File and Directory Handling
|
||||
* @include: gio/gio.h
|
||||
* @see_also: #GFileInfo, #GFileEnumerator
|
||||
* GFile:
|
||||
*
|
||||
* #GFile is a high level abstraction for manipulating files on a
|
||||
* virtual file system. #GFiles are lightweight, immutable objects
|
||||
* `GFile` is a high level abstraction for manipulating files on a
|
||||
* virtual file system. `GFile`s are lightweight, immutable objects
|
||||
* that do no I/O upon creation. It is necessary to understand that
|
||||
* #GFile objects do not represent files, merely an identifier for a
|
||||
* `GFile` objects do not represent files, merely an identifier for a
|
||||
* file. All file content I/O is implemented as streaming operations
|
||||
* (see #GInputStream and #GOutputStream).
|
||||
* (see [class@Gio.InputStream] and [class@Gio.OutputStream]).
|
||||
*
|
||||
* To construct a #GFile, you can use:
|
||||
* - g_file_new_for_path() if you have a path.
|
||||
* - g_file_new_for_uri() if you have a URI.
|
||||
* - g_file_new_for_commandline_arg() for a command line argument.
|
||||
* - g_file_new_tmp() to create a temporary file from a template.
|
||||
* - g_file_new_tmp_async() to asynchronously create a temporary file.
|
||||
* - g_file_new_tmp_dir_async() to asynchronously create a temporary directory.
|
||||
* - g_file_parse_name() from a UTF-8 string gotten from g_file_get_parse_name().
|
||||
* - g_file_new_build_filename() or g_file_new_build_filenamev() to create a file from path elements.
|
||||
* To construct a `GFile`, you can use:
|
||||
*
|
||||
* One way to think of a #GFile is as an abstraction of a pathname. For
|
||||
* - [func@Gio.File.new_for_path] if you have a path.
|
||||
* - [func@Gio.File.new_for_uri] if you have a URI.
|
||||
* - [func@Gio.File.new_for_commandline_arg] or
|
||||
* [func@Gio.File.new_for_commandline_arg_and_cwd] for a command line
|
||||
* argument.
|
||||
* - [func@Gio.File.new_tmp] to create a temporary file from a template.
|
||||
* - [func@Gio.File.new_tmp_async] to asynchronously create a temporary file.
|
||||
* - [func@Gio.File.new_tmp_dir_async] to asynchronously create a temporary
|
||||
* directory.
|
||||
* - [func@Gio.File.parse_name] from a UTF-8 string gotten from
|
||||
* [method@Gio.File.get_parse_name].
|
||||
* - [func@Gio.File.new_build_filename] or [func@Gio.File.new_build_filenamev]
|
||||
* to create a file from path elements.
|
||||
*
|
||||
* One way to think of a `GFile` is as an abstraction of a pathname. For
|
||||
* normal files the system pathname is what is stored internally, but as
|
||||
* #GFiles are extensible it could also be something else that corresponds
|
||||
* `GFile`s are extensible it could also be something else that corresponds
|
||||
* to a pathname in a userspace implementation of a filesystem.
|
||||
*
|
||||
* #GFiles make up hierarchies of directories and files that correspond to
|
||||
* `GFile`s make up hierarchies of directories and files that correspond to
|
||||
* the files on a filesystem. You can move through the file system with
|
||||
* #GFile using g_file_get_parent() to get an identifier for the parent
|
||||
* directory, g_file_get_child() to get a child within a directory,
|
||||
* g_file_resolve_relative_path() to resolve a relative path between two
|
||||
* #GFiles. There can be multiple hierarchies, so you may not end up at
|
||||
* the same root if you repeatedly call g_file_get_parent() on two different
|
||||
* files.
|
||||
* `GFile` using [method@Gio.File.get_parent] to get an identifier for the
|
||||
* parent directory, [method@Gio.File.get_child] to get a child within a
|
||||
* directory, and [method@Gio.File.resolve_relative_path] to resolve a relative
|
||||
* path between two `GFile`s. There can be multiple hierarchies, so you may not
|
||||
* end up at the same root if you repeatedly call [method@Gio.File.get_parent]
|
||||
* on two different files.
|
||||
*
|
||||
* All #GFiles have a basename (get with g_file_get_basename()). These names
|
||||
* are byte strings that are used to identify the file on the filesystem
|
||||
* All `GFile`s have a basename (get with [method@Gio.File.get_basename]). These
|
||||
* names are byte strings that are used to identify the file on the filesystem
|
||||
* (relative to its parent directory) and there is no guarantees that they
|
||||
* have any particular charset encoding or even make any sense at all. If
|
||||
* you want to use filenames in a user interface you should use the display
|
||||
* name that you can get by requesting the
|
||||
* %G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME attribute with g_file_query_info().
|
||||
* This is guaranteed to be in UTF-8 and can be used in a user interface.
|
||||
* But always store the real basename or the #GFile to use to actually
|
||||
* access the file, because there is no way to go from a display name to
|
||||
* the actual name.
|
||||
* `G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME` attribute with
|
||||
* [method@Gio.File.query_info]. This is guaranteed to be in UTF-8 and can be
|
||||
* used in a user interface. But always store the real basename or the `GFile`
|
||||
* to use to actually access the file, because there is no way to go from a
|
||||
* display name to the actual name.
|
||||
*
|
||||
* Using #GFile as an identifier has the same weaknesses as using a path
|
||||
* Using `GFile` as an identifier has the same weaknesses as using a path
|
||||
* in that there may be multiple aliases for the same file. For instance,
|
||||
* hard or soft links may cause two different #GFiles to refer to the same
|
||||
* hard or soft links may cause two different `GFile`s to refer to the same
|
||||
* file. Other possible causes for aliases are: case insensitive filesystems,
|
||||
* short and long names on FAT/NTFS, or bind mounts in Linux. If you want to
|
||||
* check if two #GFiles point to the same file you can query for the
|
||||
* %G_FILE_ATTRIBUTE_ID_FILE attribute. Note that #GFile does some trivial
|
||||
* check if two `GFile`s point to the same file you can query for the
|
||||
* `G_FILE_ATTRIBUTE_ID_FILE` attribute. Note that `GFile` does some trivial
|
||||
* canonicalization of pathnames passed in, so that trivial differences in
|
||||
* the path string used at creation (duplicated slashes, slash at end of
|
||||
* path, "." or ".." path segments, etc) does not create different #GFiles.
|
||||
* path, `.` or `..` path segments, etc) does not create different `GFile`s.
|
||||
*
|
||||
* Many #GFile operations have both synchronous and asynchronous versions
|
||||
* Many `GFile` operations have both synchronous and asynchronous versions
|
||||
* to suit your application. Asynchronous versions of synchronous functions
|
||||
* simply have _async() appended to their function names. The asynchronous
|
||||
* I/O functions call a #GAsyncReadyCallback which is then used to finalize
|
||||
* the operation, producing a GAsyncResult which is then passed to the
|
||||
* function's matching _finish() operation.
|
||||
* simply have `_async()` appended to their function names. The asynchronous
|
||||
* I/O functions call a [callback@Gio.AsyncReadyCallback] which is then used to
|
||||
* finalize the operation, producing a [iface@Gio.AsyncResult] which is then
|
||||
* passed to the function’s matching `_finish()` operation.
|
||||
*
|
||||
* It is highly recommended to use asynchronous calls when running within a
|
||||
* shared main loop, such as in the main thread of an application. This avoids
|
||||
* I/O operations blocking other sources on the main loop from being dispatched.
|
||||
* Synchronous I/O operations should be performed from worker threads. See the
|
||||
* [introduction to asynchronous programming section][async-programming] for
|
||||
* more.
|
||||
* [introduction to asynchronous programming section](overview.html#asynchronous-programming)
|
||||
* for more.
|
||||
*
|
||||
* Some #GFile operations almost always take a noticeable amount of time, and
|
||||
* Some `GFile` operations almost always take a noticeable amount of time, and
|
||||
* so do not have synchronous analogs. Notable cases include:
|
||||
* - g_file_mount_mountable() to mount a mountable file.
|
||||
* - g_file_unmount_mountable_with_operation() to unmount a mountable file.
|
||||
* - g_file_eject_mountable_with_operation() to eject a mountable file.
|
||||
*
|
||||
* ## Entity Tags # {#gfile-etag}
|
||||
* - [method@Gio.File.mount_mountable] to mount a mountable file.
|
||||
* - [method@Gio.File.unmount_mountable_with_operation] to unmount a mountable
|
||||
* file.
|
||||
* - [method@Gio.File.eject_mountable_with_operation] to eject a mountable file.
|
||||
*
|
||||
* One notable feature of #GFiles are entity tags, or "etags" for
|
||||
* ## Entity Tags
|
||||
*
|
||||
* One notable feature of `GFile`s are entity tags, or ‘etags’ for
|
||||
* short. Entity tags are somewhat like a more abstract version of the
|
||||
* traditional mtime, and can be used to quickly determine if the file
|
||||
* has been modified from the version on the file system. See the
|
||||
* HTTP 1.1
|
||||
* [specification](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html)
|
||||
* for HTTP Etag headers, which are a very similar concept.
|
||||
* for HTTP `ETag` headers, which are a very similar concept.
|
||||
*/
|
||||
|
||||
static void g_file_real_query_info_async (GFile *file,
|
||||
@ -1833,7 +1838,7 @@ g_file_create (GFile *file,
|
||||
/**
|
||||
* g_file_replace:
|
||||
* @file: input #GFile
|
||||
* @etag: (nullable): an optional [entity tag][gfile-etag]
|
||||
* @etag: (nullable): an optional [entity tag](#entity-tags)
|
||||
* for the current #GFile, or #NULL to ignore
|
||||
* @make_backup: %TRUE if a backup should be created
|
||||
* @flags: a set of #GFileCreateFlags
|
||||
@ -2038,7 +2043,7 @@ g_file_create_readwrite (GFile *file,
|
||||
/**
|
||||
* g_file_replace_readwrite:
|
||||
* @file: a #GFile
|
||||
* @etag: (nullable): an optional [entity tag][gfile-etag]
|
||||
* @etag: (nullable): an optional [entity tag](#entity-tags)
|
||||
* for the current #GFile, or #NULL to ignore
|
||||
* @make_backup: %TRUE if a backup should be created
|
||||
* @flags: a set of #GFileCreateFlags
|
||||
@ -2302,7 +2307,7 @@ g_file_create_finish (GFile *file,
|
||||
/**
|
||||
* g_file_replace_async:
|
||||
* @file: input #GFile
|
||||
* @etag: (nullable): an [entity tag][gfile-etag] for the current #GFile,
|
||||
* @etag: (nullable): an [entity tag](#entity-tags) for the current #GFile,
|
||||
* or %NULL to ignore
|
||||
* @make_backup: %TRUE if a backup should be created
|
||||
* @flags: a set of #GFileCreateFlags
|
||||
@ -2526,7 +2531,7 @@ g_file_create_readwrite_finish (GFile *file,
|
||||
/**
|
||||
* g_file_replace_readwrite_async:
|
||||
* @file: input #GFile
|
||||
* @etag: (nullable): an [entity tag][gfile-etag] for the current #GFile,
|
||||
* @etag: (nullable): an [entity tag](#entity-tags) for the current #GFile,
|
||||
* or %NULL to ignore
|
||||
* @make_backup: %TRUE if a backup should be created
|
||||
* @flags: a set of #GFileCreateFlags
|
||||
@ -8309,11 +8314,11 @@ g_file_load_contents_finish (GFile *file,
|
||||
* @file: input #GFile
|
||||
* @contents: (element-type guint8) (array length=length): a string containing the new contents for @file
|
||||
* @length: the length of @contents in bytes
|
||||
* @etag: (nullable): the old [entity-tag][gfile-etag] for the document,
|
||||
* @etag: (nullable): the old [entity-tag](#entity-tags) for the document,
|
||||
* or %NULL
|
||||
* @make_backup: %TRUE if a backup should be created
|
||||
* @flags: a set of #GFileCreateFlags
|
||||
* @new_etag: (out) (optional) (nullable): a location to a new [entity tag][gfile-etag]
|
||||
* @new_etag: (out) (optional) (nullable): a location to a new [entity tag](#entity-tags)
|
||||
* for the document. This should be freed with g_free() when no longer
|
||||
* needed, or %NULL
|
||||
* @cancellable: optional #GCancellable object, %NULL to ignore
|
||||
@ -8516,7 +8521,7 @@ replace_contents_open_callback (GObject *obj,
|
||||
* @file: input #GFile
|
||||
* @contents: (element-type guint8) (array length=length): string of contents to replace the file with
|
||||
* @length: the length of @contents in bytes
|
||||
* @etag: (nullable): a new [entity tag][gfile-etag] for the @file, or %NULL
|
||||
* @etag: (nullable): a new [entity tag](#entity-tags) for the @file, or %NULL
|
||||
* @make_backup: %TRUE if a backup should be created
|
||||
* @flags: a set of #GFileCreateFlags
|
||||
* @cancellable: optional #GCancellable object, %NULL to ignore
|
||||
@ -8566,7 +8571,7 @@ g_file_replace_contents_async (GFile *file,
|
||||
* g_file_replace_contents_bytes_async:
|
||||
* @file: input #GFile
|
||||
* @contents: a #GBytes
|
||||
* @etag: (nullable): a new [entity tag][gfile-etag] for the @file, or %NULL
|
||||
* @etag: (nullable): a new [entity tag](#entity-tags) for the @file, or %NULL
|
||||
* @make_backup: %TRUE if a backup should be created
|
||||
* @flags: a set of #GFileCreateFlags
|
||||
* @cancellable: optional #GCancellable object, %NULL to ignore
|
||||
@ -8621,7 +8626,7 @@ g_file_replace_contents_bytes_async (GFile *file,
|
||||
* g_file_replace_contents_finish:
|
||||
* @file: input #GFile
|
||||
* @res: a #GAsyncResult
|
||||
* @new_etag: (out) (optional) (nullable): a location of a new [entity tag][gfile-etag]
|
||||
* @new_etag: (out) (optional) (nullable): a location of a new [entity tag](#entity-tags)
|
||||
* for the document. This should be freed with g_free() when it is no
|
||||
* longer needed, or %NULL
|
||||
* @error: a #GError, or %NULL
|
||||
|
10
gio/gfile.h
10
gio/gfile.h
@ -36,16 +36,6 @@ G_BEGIN_DECLS
|
||||
#define G_IS_FILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_FILE))
|
||||
#define G_FILE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_FILE, GFileIface))
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* GFile:
|
||||
*
|
||||
* A handle to an object implementing the #GFileIface interface.
|
||||
* Generally stores a location within the file system. Handles do not
|
||||
* necessarily represent files or directories that currently exist.
|
||||
**/
|
||||
typedef struct _GFile GFile; /* Dummy typedef */
|
||||
#endif
|
||||
typedef struct _GFileIface GFileIface;
|
||||
|
||||
|
||||
|
@ -2066,7 +2066,7 @@ g_file_info_get_symlink_target (GFileInfo *info)
|
||||
* g_file_info_get_etag:
|
||||
* @info: a #GFileInfo.
|
||||
*
|
||||
* Gets the [entity tag][gfile-etag] for a given
|
||||
* Gets the [entity tag](iface.File.html#entity-tags) for a given
|
||||
* #GFileInfo. See %G_FILE_ATTRIBUTE_ETAG_VALUE.
|
||||
*
|
||||
* It is an error to call this if the #GFileInfo does not contain
|
||||
|
@ -34,31 +34,28 @@
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:gfileiostream
|
||||
* @short_description: File read and write streaming operations
|
||||
* @include: gio/gio.h
|
||||
* @see_also: #GIOStream, #GFileInputStream, #GFileOutputStream, #GSeekable
|
||||
* GFileIOStream:
|
||||
*
|
||||
* GFileIOStream provides io streams that both read and write to the same
|
||||
* `GFileIOStream` provides I/O streams that both read and write to the same
|
||||
* file handle.
|
||||
*
|
||||
* GFileIOStream implements #GSeekable, which allows the io
|
||||
* `GFileIOStream` implements [iface@Gio.Seekable], which allows the I/O
|
||||
* stream to jump to arbitrary positions in the file and to truncate
|
||||
* the file, provided the filesystem of the file supports these
|
||||
* operations.
|
||||
*
|
||||
* To find the position of a file io stream, use
|
||||
* g_seekable_tell().
|
||||
* To find the position of a file I/O stream, use [method@Gio.Seekable.tell].
|
||||
*
|
||||
* To find out if a file io stream supports seeking, use g_seekable_can_seek().
|
||||
* To position a file io stream, use g_seekable_seek().
|
||||
* To find out if a file io stream supports truncating, use
|
||||
* g_seekable_can_truncate(). To truncate a file io
|
||||
* stream, use g_seekable_truncate().
|
||||
* To find out if a file I/O stream supports seeking, use
|
||||
* [method@Gio.Seekable.can_seek]. To position a file I/O stream, use
|
||||
* [method@Gio.Seekable.seek]. To find out if a file I/O stream supports
|
||||
* truncating, use [method@Gio.Seekable.can_truncate]. To truncate a file I/O
|
||||
* stream, use [method@Gio.Seekable.truncate].
|
||||
*
|
||||
* The default implementation of all the `GFileIOStream` operations
|
||||
* and the implementation of [iface@Gio.Seekable] just call into the same
|
||||
* operations on the output stream.
|
||||
*
|
||||
* The default implementation of all the #GFileIOStream operations
|
||||
* and the implementation of #GSeekable just call into the same operations
|
||||
* on the output stream.
|
||||
* Since: 2.22
|
||||
**/
|
||||
|
||||
|
@ -38,14 +38,6 @@ G_BEGIN_DECLS
|
||||
#define G_IS_FILE_IO_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_FILE_IO_STREAM))
|
||||
#define G_FILE_IO_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_FILE_IO_STREAM, GFileIOStreamClass))
|
||||
|
||||
/**
|
||||
* GFileIOStream:
|
||||
*
|
||||
* A subclass of GIOStream for opened files. This adds
|
||||
* a few file-specific operations and seeking and truncating.
|
||||
*
|
||||
* #GFileIOStream implements GSeekable.
|
||||
**/
|
||||
typedef struct _GFileIOStreamClass GFileIOStreamClass;
|
||||
typedef struct _GFileIOStreamPrivate GFileIOStreamPrivate;
|
||||
|
||||
|
@ -30,14 +30,6 @@
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SECTION:gioerror
|
||||
* @short_description: Error helper functions
|
||||
* @include: gio/gio.h
|
||||
*
|
||||
* Contains helper functions for reporting errors to the user.
|
||||
**/
|
||||
|
||||
/**
|
||||
* g_io_error_quark:
|
||||
*
|
||||
|
@ -77,53 +77,47 @@
|
||||
#undef __GLIB_H_INSIDE__
|
||||
|
||||
/**
|
||||
* SECTION:giomodule
|
||||
* @short_description: Loadable GIO Modules
|
||||
* @include: gio/gio.h
|
||||
* GIOModule:
|
||||
*
|
||||
* Provides an interface and default functions for loading and unloading
|
||||
* modules. This is used internally to make GIO extensible, but can also
|
||||
* be used by others to implement module loading.
|
||||
*
|
||||
**/
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:extensionpoints
|
||||
* @short_description: Extension Points
|
||||
* @include: gio.h
|
||||
* @see_also: [Extending GIO][extending-gio]
|
||||
* GIOExtensionPoint:
|
||||
*
|
||||
* #GIOExtensionPoint provides a mechanism for modules to extend the
|
||||
* `GIOExtensionPoint` provides a mechanism for modules to extend the
|
||||
* functionality of the library or application that loaded it in an
|
||||
* organized fashion.
|
||||
* organized fashion.
|
||||
*
|
||||
* An extension point is identified by a name, and it may optionally
|
||||
* require that any implementation must be of a certain type (or derived
|
||||
* thereof). Use g_io_extension_point_register() to register an
|
||||
* extension point, and g_io_extension_point_set_required_type() to
|
||||
* thereof). Use [func@Gio.IOExtensionPoint.register] to register an
|
||||
* extension point, and [method@Gio.IOExtensionPoint.set_required_type] to
|
||||
* set a required type.
|
||||
*
|
||||
* A module can implement an extension point by specifying the #GType
|
||||
* that implements the functionality. Additionally, each implementation
|
||||
* of an extension point has a name, and a priority. Use
|
||||
* g_io_extension_point_implement() to implement an extension point.
|
||||
* A module can implement an extension point by specifying the
|
||||
* [type@GObject.Type] that implements the functionality. Additionally, each
|
||||
* implementation of an extension point has a name, and a priority. Use
|
||||
* [func@Gio.IOExtensionPoint.implement] to implement an extension point.
|
||||
*
|
||||
* |[<!-- language="C" -->
|
||||
* GIOExtensionPoint *ep;
|
||||
* ```c
|
||||
* GIOExtensionPoint *ep;
|
||||
*
|
||||
* // Register an extension point
|
||||
* ep = g_io_extension_point_register ("my-extension-point");
|
||||
* g_io_extension_point_set_required_type (ep, MY_TYPE_EXAMPLE);
|
||||
* ]|
|
||||
* // Register an extension point
|
||||
* ep = g_io_extension_point_register ("my-extension-point");
|
||||
* g_io_extension_point_set_required_type (ep, MY_TYPE_EXAMPLE);
|
||||
* ```
|
||||
*
|
||||
* |[<!-- language="C" -->
|
||||
* // Implement an extension point
|
||||
* G_DEFINE_TYPE (MyExampleImpl, my_example_impl, MY_TYPE_EXAMPLE)
|
||||
* g_io_extension_point_implement ("my-extension-point",
|
||||
* my_example_impl_get_type (),
|
||||
* "my-example",
|
||||
* 10);
|
||||
* ]|
|
||||
* ```c
|
||||
* // Implement an extension point
|
||||
* G_DEFINE_TYPE (MyExampleImpl, my_example_impl, MY_TYPE_EXAMPLE)
|
||||
* g_io_extension_point_implement ("my-extension-point",
|
||||
* my_example_impl_get_type (),
|
||||
* "my-example",
|
||||
* 10);
|
||||
* ```
|
||||
*
|
||||
* It is up to the code that registered the extension point how
|
||||
* it uses the implementations that have been associated with it.
|
||||
@ -133,7 +127,7 @@
|
||||
*
|
||||
* To avoid opening all modules just to find out what extension
|
||||
* points they implement, GIO makes use of a caching mechanism,
|
||||
* see [gio-querymodules][gio-querymodules].
|
||||
* see [gio-querymodules](gio-querymodules.html).
|
||||
* You are expected to run this command after installing a
|
||||
* GIO module.
|
||||
*
|
||||
@ -267,12 +261,6 @@ struct _GIOExtension {
|
||||
gint priority;
|
||||
};
|
||||
|
||||
/**
|
||||
* GIOExtensionPoint:
|
||||
*
|
||||
* #GIOExtensionPoint is an opaque data structure and can only be accessed
|
||||
* using the following functions.
|
||||
*/
|
||||
struct _GIOExtensionPoint {
|
||||
GType required_type;
|
||||
char *name;
|
||||
|
@ -49,11 +49,6 @@ void g_io_module_scope_block (GIOModuleScope *scope,
|
||||
#define G_IO_IS_MODULE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_IO_TYPE_MODULE))
|
||||
#define G_IO_MODULE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_IO_TYPE_MODULE, GIOModuleClass))
|
||||
|
||||
/**
|
||||
* GIOModule:
|
||||
*
|
||||
* Opaque module base class for extending GIO.
|
||||
**/
|
||||
typedef struct _GIOModuleClass GIOModuleClass;
|
||||
|
||||
GIO_AVAILABLE_IN_ALL
|
||||
|
@ -76,13 +76,6 @@ typedef struct _GFileMonitor GFileMonitor;
|
||||
typedef struct _GFilterInputStream GFilterInputStream;
|
||||
typedef struct _GFilterOutputStream GFilterOutputStream;
|
||||
|
||||
/**
|
||||
* GFile:
|
||||
*
|
||||
* A handle to an object implementing the #GFileIface interface.
|
||||
* Generally stores a location within the file system. Handles do not
|
||||
* necessarily represent files or directories that currently exist.
|
||||
**/
|
||||
typedef struct _GFile GFile; /* Dummy typedef */
|
||||
typedef struct _GFileInfo GFileInfo;
|
||||
|
||||
@ -162,12 +155,6 @@ typedef struct _GSimpleAsyncResult GSimpleAsyncResult;
|
||||
**/
|
||||
typedef struct _GSocket GSocket;
|
||||
|
||||
/**
|
||||
* GSocketControlMessage:
|
||||
*
|
||||
* Base class for socket-type specific control messages that can be sent and
|
||||
* received over #GSocket.
|
||||
**/
|
||||
typedef struct _GSocketControlMessage GSocketControlMessage;
|
||||
/**
|
||||
* GSocketClient:
|
||||
@ -638,13 +625,6 @@ typedef GType (*GDBusProxyTypeFunc) (GDBusObjectManagerClient *manager,
|
||||
|
||||
typedef struct _GTestDBus GTestDBus;
|
||||
|
||||
/**
|
||||
* GSubprocess:
|
||||
*
|
||||
* A child process.
|
||||
*
|
||||
* Since: 2.40
|
||||
*/
|
||||
typedef struct _GSubprocess GSubprocess;
|
||||
/**
|
||||
* GSubprocessLauncher:
|
||||
|
@ -24,17 +24,15 @@
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:gsocketconnectable
|
||||
* @short_description: Interface for potential socket endpoints
|
||||
* @include: gio/gio.h
|
||||
* GSocketConnectable:
|
||||
*
|
||||
* Objects that describe one or more potential socket endpoints
|
||||
* implement #GSocketConnectable. Callers can then use
|
||||
* g_socket_connectable_enumerate() to get a #GSocketAddressEnumerator
|
||||
* to try out each socket address in turn until one succeeds, as shown
|
||||
* in the sample code below.
|
||||
* implement `GSocketConnectable`. Callers can then use
|
||||
* [method@Gio.SocketConnectable.enumerate] to get a
|
||||
* [class@Gio.SocketAddressEnumerator] to try out each socket address in turn
|
||||
* until one succeeds, as shown in the sample code below.
|
||||
*
|
||||
* |[<!-- language="C" -->
|
||||
* ```c
|
||||
* MyConnectionType *
|
||||
* connect_to_host (const char *hostname,
|
||||
* guint16 port,
|
||||
@ -84,7 +82,7 @@
|
||||
* return NULL;
|
||||
* }
|
||||
* }
|
||||
* ]|
|
||||
* ```
|
||||
*/
|
||||
|
||||
|
||||
|
@ -34,11 +34,6 @@ G_BEGIN_DECLS
|
||||
#define G_IS_SOCKET_CONNECTABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_SOCKET_CONNECTABLE))
|
||||
#define G_SOCKET_CONNECTABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_SOCKET_CONNECTABLE, GSocketConnectableIface))
|
||||
|
||||
/**
|
||||
* GSocketConnectable:
|
||||
*
|
||||
* Interface for objects that contain or generate a #GSocketAddress.
|
||||
*/
|
||||
typedef struct _GSocketConnectableIface GSocketConnectableIface;
|
||||
|
||||
/**
|
||||
|
@ -15,32 +15,28 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:gsocketcontrolmessage
|
||||
* @title: GSocketControlMessage
|
||||
* @short_description: A GSocket control message
|
||||
* @include: gio/gio.h
|
||||
* @see_also: #GSocket.
|
||||
* GSocketControlMessage:
|
||||
*
|
||||
* A #GSocketControlMessage is a special-purpose utility message that
|
||||
* can be sent to or received from a #GSocket. These types of
|
||||
* messages are often called "ancillary data".
|
||||
* A `GSocketControlMessage` is a special-purpose utility message that
|
||||
* can be sent to or received from a [class@Gio.Socket]. These types of
|
||||
* messages are often called ‘ancillary data’.
|
||||
*
|
||||
* The message can represent some sort of special instruction to or
|
||||
* information from the socket or can represent a special kind of
|
||||
* transfer to the peer (for example, sending a file descriptor over
|
||||
* a UNIX socket).
|
||||
*
|
||||
* These messages are sent with g_socket_send_message() and received
|
||||
* with g_socket_receive_message().
|
||||
* These messages are sent with [method@Gio.Socket.send_message] and received
|
||||
* with [method@Gio.Socket.receive_message].
|
||||
*
|
||||
* To extend the set of control message that can be sent, subclass this
|
||||
* class and override the get_size, get_level, get_type and serialize
|
||||
* class and override the `get_size`, `get_level`, `get_type` and `serialize`
|
||||
* methods.
|
||||
*
|
||||
* To extend the set of control messages that can be received, subclass
|
||||
* this class and implement the deserialize method. Also, make sure your
|
||||
* class is registered with the GType typesystem before calling
|
||||
* g_socket_receive_message() to read such a message.
|
||||
* this class and implement the `deserialize` method. Also, make sure your
|
||||
* class is registered with the [type@GObject.Type] type system before calling
|
||||
* [method@Gio.Socket.receive_message] to read such a message.
|
||||
*
|
||||
* Since: 2.22
|
||||
*/
|
||||
|
@ -17,18 +17,14 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:gsubprocess
|
||||
* @title: GSubprocess
|
||||
* @short_description: Child processes
|
||||
* @include: gio/gio.h
|
||||
* @see_also: #GSubprocessLauncher
|
||||
* GSubprocess:
|
||||
*
|
||||
* #GSubprocess allows the creation of and interaction with child
|
||||
* `GSubprocess` allows the creation of and interaction with child
|
||||
* processes.
|
||||
*
|
||||
* Processes can be communicated with using standard GIO-style APIs (ie:
|
||||
* #GInputStream, #GOutputStream). There are GIO-style APIs to wait for
|
||||
* process termination (ie: cancellable and with an asynchronous
|
||||
* [class@Gio.InputStream], [class@Gio.OutputStream]). There are GIO-style APIs
|
||||
* to wait for process termination (ie: cancellable and with an asynchronous
|
||||
* variant).
|
||||
*
|
||||
* There is an API to force a process to terminate, as well as a
|
||||
@ -36,50 +32,50 @@
|
||||
*
|
||||
* One major advantage that GIO brings over the core GLib library is
|
||||
* comprehensive API for asynchronous I/O, such
|
||||
* g_output_stream_splice_async(). This makes GSubprocess
|
||||
* [method@Gio.OutputStream.splice_async]. This makes `GSubprocess`
|
||||
* significantly more powerful and flexible than equivalent APIs in
|
||||
* some other languages such as the `subprocess.py`
|
||||
* included with Python. For example, using #GSubprocess one could
|
||||
* included with Python. For example, using `GSubprocess` one could
|
||||
* create two child processes, reading standard output from the first,
|
||||
* processing it, and writing to the input stream of the second, all
|
||||
* without blocking the main loop.
|
||||
*
|
||||
* A powerful g_subprocess_communicate() API is provided similar to the
|
||||
* A powerful [method@Gio.Subprocess.communicate] API is provided similar to the
|
||||
* `communicate()` method of `subprocess.py`. This enables very easy
|
||||
* interaction with a subprocess that has been opened with pipes.
|
||||
*
|
||||
* #GSubprocess defaults to tight control over the file descriptors open
|
||||
* in the child process, avoiding dangling-fd issues that are caused by
|
||||
* a simple fork()/exec(). The only open file descriptors in the
|
||||
* `GSubprocess` defaults to tight control over the file descriptors open
|
||||
* in the child process, avoiding dangling-FD issues that are caused by
|
||||
* a simple `fork()`/`exec()`. The only open file descriptors in the
|
||||
* spawned process are ones that were explicitly specified by the
|
||||
* #GSubprocess API (unless %G_SUBPROCESS_FLAGS_INHERIT_FDS was
|
||||
* `GSubprocess` API (unless `G_SUBPROCESS_FLAGS_INHERIT_FDS` was
|
||||
* specified).
|
||||
*
|
||||
* #GSubprocess will quickly reap all child processes as they exit,
|
||||
* avoiding "zombie processes" remaining around for long periods of
|
||||
* time. g_subprocess_wait() can be used to wait for this to happen,
|
||||
* `GSubprocess` will quickly reap all child processes as they exit,
|
||||
* avoiding ‘zombie processes’ remaining around for long periods of
|
||||
* time. [method@Gio.Subprocess.wait] can be used to wait for this to happen,
|
||||
* but it will happen even without the call being explicitly made.
|
||||
*
|
||||
* As a matter of principle, #GSubprocess has no API that accepts
|
||||
* As a matter of principle, `GSubprocess` has no API that accepts
|
||||
* shell-style space-separated strings. It will, however, match the
|
||||
* typical shell behaviour of searching the PATH for executables that do
|
||||
* typical shell behaviour of searching the `PATH` for executables that do
|
||||
* not contain a directory separator in their name. By default, the `PATH`
|
||||
* of the current process is used. You can specify
|
||||
* %G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP to use the `PATH` of the
|
||||
* `G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP` to use the `PATH` of the
|
||||
* launcher environment instead.
|
||||
*
|
||||
* #GSubprocess attempts to have a very simple API for most uses (ie:
|
||||
* `GSubprocess` attempts to have a very simple API for most uses (ie:
|
||||
* spawning a subprocess with arguments and support for most typical
|
||||
* kinds of input and output redirection). See g_subprocess_new(). The
|
||||
* #GSubprocessLauncher API is provided for more complicated cases
|
||||
* kinds of input and output redirection). See [ctor@Gio.Subprocess.new]. The
|
||||
* [class@Gio.SubprocessLauncher] API is provided for more complicated cases
|
||||
* (advanced types of redirection, environment variable manipulation,
|
||||
* change of working directory, child setup functions, etc).
|
||||
*
|
||||
* A typical use of #GSubprocess will involve calling
|
||||
* g_subprocess_new(), followed by g_subprocess_wait_async() or
|
||||
* g_subprocess_wait(). After the process exits, the status can be
|
||||
* checked using functions such as g_subprocess_get_if_exited() (which
|
||||
* are similar to the familiar WIFEXITED-style POSIX macros).
|
||||
* A typical use of `GSubprocess` will involve calling
|
||||
* [ctor@Gio.Subprocess.new], followed by [method@Gio.Subprocess.wait_async] or
|
||||
* [method@Gio.Subprocess.wait]. After the process exits, the status can be
|
||||
* checked using functions such as [method@Gio.Subprocess.get_if_exited] (which
|
||||
* are similar to the familiar `WIFEXITED`-style POSIX macros).
|
||||
*
|
||||
* Since: 2.40
|
||||
**/
|
||||
|
829
gio/gtask.c
829
gio/gtask.c
@ -33,520 +33,518 @@
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* SECTION:gtask
|
||||
* @short_description: Cancellable synchronous or asynchronous task
|
||||
* and result
|
||||
* @include: gio/gio.h
|
||||
* @see_also: #GAsyncResult
|
||||
* GTask:
|
||||
*
|
||||
* A #GTask represents and manages a cancellable "task".
|
||||
* A `GTask` represents and manages a cancellable ‘task’.
|
||||
*
|
||||
* ## Asynchronous operations
|
||||
*
|
||||
* The most common usage of #GTask is as a #GAsyncResult, to
|
||||
* The most common usage of `GTask` is as a [iface@Gio.AsyncResult], to
|
||||
* manage data during an asynchronous operation. You call
|
||||
* g_task_new() in the "start" method, followed by
|
||||
* g_task_set_task_data() and the like if you need to keep some
|
||||
* [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
|
||||
* g_task_return_pointer() or g_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][g-main-context-push-thread-default]
|
||||
* [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 #GAsyncResult), and you can
|
||||
* use g_task_propagate_pointer() or the like to extract the
|
||||
* 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 #GMainContext from when the
|
||||
* #GTask was constructed to be running at least until the task has completed
|
||||
* and its data has been freed.
|
||||
* 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
|
||||
* 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 GAsyncResult:
|
||||
* |[<!-- language="C" -->
|
||||
* typedef struct {
|
||||
* CakeFrostingType frosting;
|
||||
* char *message;
|
||||
* } DecorationData;
|
||||
* 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)
|
||||
* 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_free (decoration->message);
|
||||
* g_slice_free (DecorationData, decoration);
|
||||
* g_task_return_new_error (task, BAKER_ERROR, BAKER_ERROR_NO_FLOUR,
|
||||
* "Go to the supermarket");
|
||||
* g_object_unref (task);
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* static void
|
||||
* baked_cb (Cake *cake,
|
||||
* gpointer user_data)
|
||||
* if (!cake_decorate (cake, decoration->frosting, decoration->message, &error))
|
||||
* {
|
||||
* GTask *task = user_data;
|
||||
* DecorationData *decoration = g_task_get_task_data (task);
|
||||
* GError *error = NULL;
|
||||
* g_object_unref (cake);
|
||||
* // g_task_return_error() takes ownership of error
|
||||
* g_task_return_error (task, error);
|
||||
* g_object_unref (task);
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* if (cake == NULL)
|
||||
* {
|
||||
* g_task_return_new_error (task, BAKER_ERROR, BAKER_ERROR_NO_FLOUR,
|
||||
* "Go to the supermarket");
|
||||
* g_object_unref (task);
|
||||
* return;
|
||||
* }
|
||||
* g_task_return_pointer (task, cake, g_object_unref);
|
||||
* g_object_unref (task);
|
||||
* }
|
||||
*
|
||||
* 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;
|
||||
* }
|
||||
* 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;
|
||||
* }
|
||||
*
|
||||
* 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;
|
||||
* decoration = g_slice_new (DecorationData);
|
||||
* decoration->frosting = frosting;
|
||||
* decoration->message = g_strdup (message);
|
||||
* g_task_set_task_data (task, decoration, (GDestroyNotify) decoration_data_free);
|
||||
*
|
||||
* 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;
|
||||
* }
|
||||
* _baker_begin_cake (self, radius, flavor, cancellable, baked_cb, task);
|
||||
* }
|
||||
*
|
||||
* 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;
|
||||
* }
|
||||
* Cake *
|
||||
* baker_bake_cake_finish (Baker *self,
|
||||
* GAsyncResult *result,
|
||||
* GError **error)
|
||||
* {
|
||||
* g_return_val_if_fail (g_task_is_valid (result, self), NULL);
|
||||
*
|
||||
* 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);
|
||||
* }
|
||||
* ]|
|
||||
* return g_task_propagate_pointer (G_TASK (result), error);
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* ## Chained asynchronous operations
|
||||
*
|
||||
* #GTask also tries to simplify asynchronous operations that
|
||||
* `GTask` also tries to simplify asynchronous operations that
|
||||
* internally chain together several smaller asynchronous
|
||||
* operations. g_task_get_cancellable(), g_task_get_context(),
|
||||
* and g_task_get_priority() allow you to get back the task's
|
||||
* #GCancellable, #GMainContext, and [I/O priority][io-priority]
|
||||
* when starting a new subtask, so you don't have to keep track
|
||||
* of them yourself. g_task_attach_source() simplifies the case
|
||||
* 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
|
||||
* #GMainContext and priority).
|
||||
* [struct@GLib.MainContext] and priority).
|
||||
*
|
||||
* Here is an example for chained asynchronous operations:
|
||||
* |[<!-- language="C" -->
|
||||
* typedef struct {
|
||||
* Cake *cake;
|
||||
* CakeFrostingType frosting;
|
||||
* char *message;
|
||||
* } BakingData;
|
||||
* ```c
|
||||
* typedef struct {
|
||||
* Cake *cake;
|
||||
* CakeFrostingType frosting;
|
||||
* char *message;
|
||||
* } BakingData;
|
||||
*
|
||||
* static void
|
||||
* decoration_data_free (BakingData *bd)
|
||||
* 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))
|
||||
* {
|
||||
* 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 (cake);
|
||||
* g_task_return_error (task, error);
|
||||
* g_object_unref (task);
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* static gboolean
|
||||
* decorator_ready (gpointer user_data)
|
||||
* // 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)
|
||||
* {
|
||||
* 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;
|
||||
* g_task_return_new_error (task, BAKER_ERROR, BAKER_ERROR_NO_FLOUR,
|
||||
* "Go to the supermarket");
|
||||
* g_object_unref (task);
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* static void
|
||||
* baked_cb (Cake *cake,
|
||||
* gpointer user_data)
|
||||
* bd->cake = cake;
|
||||
*
|
||||
* // Bail out now if the user has already cancelled
|
||||
* if (g_task_return_error_if_cancelled (task))
|
||||
* {
|
||||
* 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);
|
||||
* }
|
||||
* g_object_unref (task);
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* 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)
|
||||
* if (cake_decorator_available (cake))
|
||||
* decorator_ready (task);
|
||||
* else
|
||||
* {
|
||||
* GTask *task;
|
||||
* BakingData *bd;
|
||||
* GSource *source;
|
||||
*
|
||||
* 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);
|
||||
* 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);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Cake *
|
||||
* baker_bake_cake_finish (Baker *self,
|
||||
* GAsyncResult *result,
|
||||
* GError **error)
|
||||
* {
|
||||
* g_return_val_if_fail (g_task_is_valid (result, self), NULL);
|
||||
* 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;
|
||||
*
|
||||
* return g_task_propagate_pointer (G_TASK (result), error);
|
||||
* }
|
||||
* ]|
|
||||
* 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 g_task_run_in_thread() to turn a synchronous
|
||||
* 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][g-main-context-push-thread-default]
|
||||
* where the #GTask was created.
|
||||
* 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:
|
||||
* |[<!-- language="C" -->
|
||||
* typedef struct {
|
||||
* guint radius;
|
||||
* CakeFlavor flavor;
|
||||
* CakeFrostingType frosting;
|
||||
* char *message;
|
||||
* } CakeData;
|
||||
* ```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
|
||||
* 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;
|
||||
* 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);
|
||||
* }
|
||||
* 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;
|
||||
* 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_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);
|
||||
* 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);
|
||||
* }
|
||||
* ]|
|
||||
* return g_task_propagate_pointer (G_TASK (result), error);
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* ## Adding cancellability to uncancellable tasks
|
||||
*
|
||||
* Finally, g_task_run_in_thread() and g_task_run_in_thread_sync()
|
||||
* can be used to turn an uncancellable operation into a
|
||||
* cancellable one. If you call g_task_set_return_on_cancel(),
|
||||
* passing %TRUE, then if the task's #GCancellable 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).
|
||||
* 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
|
||||
* to make ‘GLib-friendly’ asynchronous and cancellable
|
||||
* synchronous variants of blocking APIs.
|
||||
*
|
||||
* Cancelling a task:
|
||||
* |[<!-- language="C" -->
|
||||
* static void
|
||||
* bake_cake_thread (GTask *task,
|
||||
* gpointer source_object,
|
||||
* gpointer task_data,
|
||||
* GCancellable *cancellable)
|
||||
* ```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)
|
||||
* {
|
||||
* 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);
|
||||
* }
|
||||
* g_task_return_error (task, error);
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* void
|
||||
* baker_bake_cake_async (Baker *self,
|
||||
* guint radius,
|
||||
* CakeFlavor flavor,
|
||||
* CakeFrostingType frosting,
|
||||
* const char *message,
|
||||
* GCancellable *cancellable,
|
||||
* GAsyncReadyCallback callback,
|
||||
* gpointer user_data)
|
||||
* // 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))
|
||||
* {
|
||||
* 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);
|
||||
* // 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);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* 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;
|
||||
* 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 = 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);
|
||||
* 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 = g_task_propagate_pointer (task, error);
|
||||
* g_object_unref (task);
|
||||
* return cake;
|
||||
* }
|
||||
* ]|
|
||||
* 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;
|
||||
*
|
||||
* ## Porting from GSimpleAsyncResult
|
||||
* 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 #GSimpleAsyncResult's
|
||||
* `GTask`’s API attempts to be simpler than [class@Gio.SimpleAsyncResult]’s
|
||||
* in several ways:
|
||||
* - You can save task-specific data with g_task_set_task_data(), and
|
||||
* retrieve it later with g_task_get_task_data(). This replaces the
|
||||
* abuse of g_simple_async_result_set_op_res_gpointer() for the same
|
||||
* purpose with #GSimpleAsyncResult.
|
||||
* - In addition to the task data, #GTask also keeps track of the
|
||||
* [priority][io-priority], #GCancellable, and
|
||||
* #GMainContext associated with the task, so tasks that consist of
|
||||
* a chain of simpler asynchronous operations will have easy access
|
||||
*
|
||||
* - 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.
|
||||
* - g_task_return_error_if_cancelled() provides simplified
|
||||
* - [method@Gio.Task.return_error_if_cancelled] provides simplified
|
||||
* handling for cancellation. In addition, cancellation
|
||||
* overrides any other #GTask return value by default, like
|
||||
* #GSimpleAsyncResult does when
|
||||
* g_simple_async_result_set_check_cancellable() is called.
|
||||
* (You can use g_task_set_check_cancellable() to turn off that
|
||||
* behavior.) On the other hand, g_task_run_in_thread()
|
||||
* 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 #GCancellable
|
||||
* `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
|
||||
* g_task_return_error_if_cancelled() check if you need the
|
||||
* [method@Gio.Task.return_error_if_cancelled] check if you need the
|
||||
* old behavior.
|
||||
* - The "return" methods (eg, g_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 #GMainContext, or delayed
|
||||
* until the next iteration of the current #GMainContext.)
|
||||
* - The "finish" functions for #GTask based operations are generally
|
||||
* much simpler than #GSimpleAsyncResult ones, normally consisting
|
||||
* of only a single call to g_task_propagate_pointer() or the like.
|
||||
* Since g_task_propagate_pointer() "steals" the return value from
|
||||
* the #GTask, it is not necessary to juggle pointers around to
|
||||
* - 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 #GSimpleAsyncResult, it was common to call
|
||||
* g_simple_async_result_propagate_error() from the
|
||||
* - 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
|
||||
* 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
|
||||
* g_async_result_legacy_propagate_error() to do old-style
|
||||
* #GSimpleAsyncResult error-returning behavior, and
|
||||
* g_async_result_is_tagged() to check if a result is tagged as
|
||||
* [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 g_input_stream_read_async()).
|
||||
* 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:
|
||||
* 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
|
||||
@ -556,19 +554,11 @@
|
||||
* 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* GTask:
|
||||
*
|
||||
* The opaque object representing a synchronous or asynchronous task
|
||||
* and its result.
|
||||
*/
|
||||
|
||||
struct _GTask {
|
||||
GObject parent_instance;
|
||||
|
||||
@ -962,7 +952,7 @@ g_task_set_task_data (GTask *task,
|
||||
/**
|
||||
* g_task_set_priority:
|
||||
* @task: the #GTask
|
||||
* @priority: the [priority][io-priority] of the request
|
||||
* @priority: the [priority](iface.AsyncResult.html#io-priority) of the request
|
||||
*
|
||||
* Sets @task's priority. If you do not call this, it will default to
|
||||
* %G_PRIORITY_DEFAULT.
|
||||
@ -1787,8 +1777,9 @@ g_task_run_in_thread_sync (GTask *task,
|
||||
*
|
||||
* 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][io-priority], and sets @source's
|
||||
* callback to @callback, with @task as the callback's `user_data`.
|
||||
* #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
|
||||
|
@ -33,26 +33,16 @@
|
||||
#include "glibintl.h"
|
||||
#include "gmarshal-internal.h"
|
||||
|
||||
/**
|
||||
* SECTION:gtlsconnection
|
||||
* @short_description: TLS connection type
|
||||
* @include: gio/gio.h
|
||||
*
|
||||
* #GTlsConnection is the base TLS connection class type, which wraps
|
||||
* a #GIOStream and provides TLS encryption on top of it. Its
|
||||
* subclasses, #GTlsClientConnection and #GTlsServerConnection,
|
||||
* implement client-side and server-side TLS, respectively.
|
||||
*
|
||||
* For DTLS (Datagram TLS) support, see #GDtlsConnection.
|
||||
*
|
||||
* Since: 2.28
|
||||
*/
|
||||
|
||||
/**
|
||||
* GTlsConnection:
|
||||
*
|
||||
* Abstract base class for the backend-specific #GTlsClientConnection
|
||||
* and #GTlsServerConnection types.
|
||||
* `GTlsConnection` is the base TLS connection class type, which wraps
|
||||
* a [class@Gio.IOStream] and provides TLS encryption on top of it. Its
|
||||
* subclasses, [iface@Gio.TlsClientConnection] and
|
||||
* [iface@Gio.TlsServerConnection], implement client-side and server-side TLS,
|
||||
* respectively.
|
||||
*
|
||||
* For DTLS (Datagram TLS) support, see [iface@Gio.DtlsConnection].
|
||||
*
|
||||
* Since: 2.28
|
||||
*/
|
||||
|
@ -15,34 +15,23 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:gunixfdmessage
|
||||
* @title: GUnixFDMessage
|
||||
* @short_description: A GSocketControlMessage containing a GUnixFDList
|
||||
* @include: gio/gunixfdmessage.h
|
||||
* @see_also: #GUnixConnection, #GUnixFDList, #GSocketControlMessage
|
||||
* GUnixFDMessage:
|
||||
*
|
||||
* This #GSocketControlMessage contains a #GUnixFDList.
|
||||
* It may be sent using g_socket_send_message() and received using
|
||||
* g_socket_receive_message() over UNIX sockets (ie: sockets in the
|
||||
* %G_SOCKET_FAMILY_UNIX family). The file descriptors are copied
|
||||
* This [class@Gio.SocketControlMessage] contains a [class@Gio.UnixFDList].
|
||||
* It may be sent using [method@Gio.Socket.send_message] and received using
|
||||
* [method@Gio.Socket.receive_message] over UNIX sockets (ie: sockets in the
|
||||
* `G_SOCKET_FAMILY_UNIX` family). The file descriptors are copied
|
||||
* between processes by the kernel.
|
||||
*
|
||||
* For an easier way to send and receive file descriptors over
|
||||
* stream-oriented UNIX sockets, see g_unix_connection_send_fd() and
|
||||
* g_unix_connection_receive_fd().
|
||||
* stream-oriented UNIX sockets, see [method@Gio.UnixConnection.send_fd] and
|
||||
* [method@Gio.UnixConnection.receive_fd].
|
||||
*
|
||||
* Note that `<gio/gunixfdmessage.h>` belongs to the UNIX-specific GIO
|
||||
* interfaces, thus you have to use the `gio-unix-2.0.pc` pkg-config
|
||||
* file when using it.
|
||||
*/
|
||||
|
||||
/**
|
||||
* GUnixFDMessage:
|
||||
*
|
||||
* #GUnixFDMessage is an opaque data structure and can only be accessed
|
||||
* using the following functions.
|
||||
**/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
@ -31,12 +31,9 @@
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:gvfs
|
||||
* @short_description: Virtual File System
|
||||
* @include: gio/gio.h
|
||||
* GVfs:
|
||||
*
|
||||
* Entry point for using GIO functionality.
|
||||
*
|
||||
*/
|
||||
|
||||
static GRWLock additional_schemes_lock;
|
||||
|
@ -68,11 +68,6 @@ typedef GFile * (* GVfsFileLookupFunc) (GVfs *vfs,
|
||||
*/
|
||||
#define G_VFS_EXTENSION_POINT_NAME "gio-vfs"
|
||||
|
||||
/**
|
||||
* GVfs:
|
||||
*
|
||||
* Virtual File System object.
|
||||
**/
|
||||
typedef struct _GVfsClass GVfsClass;
|
||||
|
||||
struct _GVfs
|
||||
|
@ -42,19 +42,18 @@
|
||||
#include "gtestutils.h"
|
||||
|
||||
/**
|
||||
* SECTION:caches
|
||||
* @title: Caches
|
||||
* @short_description: caches allow sharing of complex data structures
|
||||
* to save resources
|
||||
* GCache:
|
||||
*
|
||||
* A #GCache allows sharing of complex data structures, in order to
|
||||
* A `GCache` allows sharing of complex data structures, in order to
|
||||
* save system resources.
|
||||
*
|
||||
* GCache uses keys and values. A GCache key describes the properties
|
||||
* of a particular resource. A GCache value is the actual resource.
|
||||
* `GCache` uses keys and values. A `GCache` key describes the properties
|
||||
* of a particular resource. A `GCache` value is the actual resource.
|
||||
*
|
||||
* GCache has been marked as deprecated, since this API is rarely
|
||||
* `GCache` has been marked as deprecated, since this API is rarely
|
||||
* used and not very actively maintained.
|
||||
*
|
||||
* Deprecated:2.32: Use a #GHashTable instead
|
||||
*/
|
||||
|
||||
typedef struct _GCacheNode GCacheNode;
|
||||
@ -66,15 +65,6 @@ struct _GCacheNode
|
||||
gint ref_count;
|
||||
};
|
||||
|
||||
/**
|
||||
* GCache:
|
||||
*
|
||||
* The #GCache struct is an opaque data structure containing
|
||||
* information about a #GCache. It should only be accessed via the
|
||||
* following functions.
|
||||
*
|
||||
* Deprecated:2.32: Use a #GHashTable instead
|
||||
*/
|
||||
struct _GCache
|
||||
{
|
||||
/* Called to create a value from a key */
|
||||
@ -147,6 +137,7 @@ g_cache_node_destroy (GCacheNode *node)
|
||||
* value corresponding to the key.
|
||||
*
|
||||
* Returns: a new #GCache value corresponding to the key.
|
||||
* Deprecated:2.32: Use a #GHashTable instead
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -157,6 +148,8 @@ g_cache_node_destroy (GCacheNode *node)
|
||||
* functions passed to g_cache_new(). The functions are passed a
|
||||
* pointer to the #GCache key or #GCache value and should free any
|
||||
* memory and other resources associated with it.
|
||||
*
|
||||
* Deprecated:2.32: Use a #GHashTable instead
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -170,6 +163,7 @@ g_cache_node_destroy (GCacheNode *node)
|
||||
* should return a duplicate of the key.
|
||||
*
|
||||
* Returns: a copy of the #GCache key
|
||||
* Deprecated:2.32: Use a #GHashTable instead
|
||||
*/
|
||||
GCache*
|
||||
g_cache_new (GCacheNewFunc value_new_func,
|
||||
|
@ -43,34 +43,6 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* SECTION:completion
|
||||
* @title: Automatic String Completion
|
||||
* @short_description: support for automatic completion using a group
|
||||
* of target strings
|
||||
*
|
||||
* #GCompletion provides support for automatic completion of a string
|
||||
* using any group of target strings. It is typically used for file
|
||||
* name completion as is common in many UNIX shells.
|
||||
*
|
||||
* A #GCompletion is created using g_completion_new(). Target items are
|
||||
* added and removed with g_completion_add_items(),
|
||||
* g_completion_remove_items() and g_completion_clear_items(). A
|
||||
* completion attempt is requested with g_completion_complete() or
|
||||
* g_completion_complete_utf8(). When no longer needed, the
|
||||
* #GCompletion is freed with g_completion_free().
|
||||
*
|
||||
* Items in the completion can be simple strings (e.g. filenames), or
|
||||
* pointers to arbitrary data structures. If data structures are used
|
||||
* you must provide a #GCompletionFunc in g_completion_new(), which
|
||||
* retrieves the item's string from the data structure. You can change
|
||||
* the way in which strings are compared by setting a different
|
||||
* #GCompletionStrncmpFunc in g_completion_set_compare().
|
||||
*
|
||||
* GCompletion has been marked as deprecated, since this API is rarely
|
||||
* used and not very actively maintained.
|
||||
**/
|
||||
|
||||
/**
|
||||
* GCompletion:
|
||||
* @items: list of target items (strings or data structures).
|
||||
@ -82,7 +54,29 @@
|
||||
* @strncmp_func: The function to use when comparing strings. Use
|
||||
* g_completion_set_compare() to modify this function.
|
||||
*
|
||||
* The data structure used for automatic completion.
|
||||
* `GCompletion` provides support for automatic completion of a string
|
||||
* using any group of target strings. It is typically used for file
|
||||
* name completion as is common in many UNIX shells.
|
||||
*
|
||||
* A `GCompletion` is created using [func@GLib.Completion.new]. Target items are
|
||||
* added and removed with [method@GLib.Completion.add_items],
|
||||
* [method@GLib.Completion.remove_items] and
|
||||
* [method@GLib.Completion.clear_items]. A completion attempt is requested with
|
||||
* [method@GLib.Completion.complete] or [method@GLib.Completion.complete_utf8].
|
||||
* When no longer needed, the `GCompletion` is freed with
|
||||
* [method@GLib.Completion.free].
|
||||
*
|
||||
* Items in the completion can be simple strings (e.g. filenames), or
|
||||
* pointers to arbitrary data structures. If data structures are used
|
||||
* you must provide a [type@GLib.CompletionFunc] in [func@GLib.Completion.new],
|
||||
* which retrieves the item’s string from the data structure. You can change
|
||||
* the way in which strings are compared by setting a different
|
||||
* [type@GLib.CompletionStrncmpFunc] in [method@GLib.Completion.set_compare].
|
||||
*
|
||||
* `GCompletion` has been marked as deprecated, since this API is rarely
|
||||
* used and not very actively maintained.
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
|
||||
/**
|
||||
@ -94,6 +88,7 @@
|
||||
* This is used when you use data structures as #GCompletion items.
|
||||
*
|
||||
* Returns: the string corresponding to the item.
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
|
||||
/**
|
||||
@ -110,6 +105,7 @@
|
||||
* the first @n bytes of @s1 is found, respectively, to be
|
||||
* less than, to match, or to be greater than the first @n
|
||||
* bytes of @s2.
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
|
||||
static void completion_check_cache (GCompletion* cmp,
|
||||
@ -124,6 +120,7 @@ static void completion_check_cache (GCompletion* cmp,
|
||||
* Creates a new #GCompletion.
|
||||
*
|
||||
* Returns: the new #GCompletion.
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
GCompletion*
|
||||
g_completion_new (GCompletionFunc func)
|
||||
|
@ -48,61 +48,53 @@
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* SECTION:relations
|
||||
* @title: Relations and Tuples
|
||||
* @short_description: tables of data which can be indexed on any
|
||||
* number of fields
|
||||
* GRelation:
|
||||
*
|
||||
* A #GRelation is a table of data which can be indexed on any number
|
||||
* of fields, rather like simple database tables. A #GRelation contains
|
||||
* A `GRelation` is a table of data which can be indexed on any number
|
||||
* of fields, rather like simple database tables. A `GRelation` contains
|
||||
* a number of records, called tuples. Each record contains a number of
|
||||
* fields. Records are not ordered, so it is not possible to find the
|
||||
* record at a particular index.
|
||||
*
|
||||
* Note that #GRelation tables are currently limited to 2 fields.
|
||||
* Note that `GRelation` tables are currently limited to 2 fields.
|
||||
*
|
||||
* To create a GRelation, use g_relation_new().
|
||||
* To create a `GRelation`, use [func@GLib.Relation.new].
|
||||
*
|
||||
* To specify which fields should be indexed, use g_relation_index().
|
||||
* To specify which fields should be indexed, use [method@GLib.Relation.index].
|
||||
* Note that this must be called before any tuples are added to the
|
||||
* #GRelation.
|
||||
* `GRelation`.
|
||||
*
|
||||
* To add records to a #GRelation use g_relation_insert().
|
||||
* To add records to a `GRelation` use [method@GLib.Relation.insert].
|
||||
*
|
||||
* To determine if a given record appears in a #GRelation, use
|
||||
* g_relation_exists(). Note that fields are compared directly, so
|
||||
* To determine if a given record appears in a `GRelation`, use
|
||||
* [method@GLib.Relation.exists]. Note that fields are compared directly, so
|
||||
* pointers must point to the exact same position (i.e. different
|
||||
* copies of the same string will not match.)
|
||||
*
|
||||
* To count the number of records which have a particular value in a
|
||||
* given field, use g_relation_count().
|
||||
* given field, use [method@GLib.Relation.count].
|
||||
*
|
||||
* To get all the records which have a particular value in a given
|
||||
* field, use g_relation_select(). To access fields of the resulting
|
||||
* records, use g_tuples_index(). To free the resulting records use
|
||||
* g_tuples_destroy().
|
||||
* field, use [method@GLib.Relation.select]. To access fields of the resulting
|
||||
* records, use [method@GLib.Tuples.index]. To free the resulting records use
|
||||
* [method@GLib.Tuples.destroy].
|
||||
*
|
||||
* To delete all records which have a particular value in a given
|
||||
* field, use g_relation_delete().
|
||||
* field, use [method@GLib.Relation.delete].
|
||||
*
|
||||
* To destroy the #GRelation, use g_relation_destroy().
|
||||
* To destroy the `GRelation`, use [method@GLib.Relation.destroy].
|
||||
*
|
||||
* To help debug #GRelation objects, use g_relation_print().
|
||||
* To help debug `GRelation` objects, use [method@GLib.Relation.print].
|
||||
*
|
||||
* GRelation has been marked as deprecated, since this API has never
|
||||
* `GRelation` has been marked as deprecated, since this API has never
|
||||
* been fully implemented, is not very actively maintained and rarely
|
||||
* used.
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
|
||||
typedef struct _GRealTuples GRealTuples;
|
||||
|
||||
/**
|
||||
* GRelation:
|
||||
*
|
||||
* The #GRelation struct is an opaque data structure to represent a
|
||||
* [Relation][glib-Relations-and-Tuples]. It should
|
||||
* only be accessed via the following functions.
|
||||
**/
|
||||
struct _GRelation
|
||||
{
|
||||
gint fields;
|
||||
@ -122,6 +114,8 @@ struct _GRelation
|
||||
* #GRelation by g_relation_select(). It only contains one public
|
||||
* member - the number of records that matched. To access the matched
|
||||
* records, you must use g_tuples_index().
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
struct _GRealTuples
|
||||
{
|
||||
|
@ -43,29 +43,6 @@ struct _GTuples
|
||||
guint len;
|
||||
};
|
||||
|
||||
/* GRelation
|
||||
*
|
||||
* Indexed Relations. Imagine a really simple table in a
|
||||
* database. Relations are not ordered. This data type is meant for
|
||||
* maintaining a N-way mapping.
|
||||
*
|
||||
* g_relation_new() creates a relation with FIELDS fields
|
||||
*
|
||||
* g_relation_destroy() frees all resources
|
||||
* g_tuples_destroy() frees the result of g_relation_select()
|
||||
*
|
||||
* g_relation_index() indexes relation FIELD with the provided
|
||||
* equality and hash functions. this must be done before any
|
||||
* calls to insert are made.
|
||||
*
|
||||
* g_relation_insert() inserts a new tuple. you are expected to
|
||||
* provide the right number of fields.
|
||||
*
|
||||
* g_relation_delete() deletes all relations with KEY in FIELD
|
||||
* g_relation_select() returns ...
|
||||
* g_relation_count() counts ...
|
||||
*/
|
||||
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
GRelation* g_relation_new (gint fields);
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
|
Loading…
Reference in New Issue
Block a user