This is a handle for managing the reference count of GVariant objects.
- See also
- GobjHandle
This is a class which manages the reference count of GVariant objects. It does not maintain its own reference count, but interfaces with that kept by the GVariant object.
GVariant objects created with one of the g_variant_new*() functions are created with a floating reference. The constructor of a GvarHandle which takes a pointer will automatically take ownership of such a newly created GVariant object, by calling g_variant_ref_sink().
GVariant objects which are obtained by one of the g_variant_get*() or similar getter functions, such as g_variant_get_child_value(), g_variant_get_variant(), g_variant_get() with a "v" or "(v)" format string, or g_variant_iter_next_value(), or as the return value of a dbus method call in gio's dbus implementation such as g_dbus_connection_call_sync(), g_dbus_connection_call_finish(), g_dbus_proxy_call_sync() or g_dbus_proxy_call_finish(), are not created with a floating reference (the variant normally already exists), but instead the reference count is incremented by the function concerned when the object is passed out to the user, so giving ownership to the user.
It follows that g_variant_ref_sink() is not called by the constructor taking a pointer if the floating reference has already been sunk. This behaviour will ensure that the handle behaves the same whether it is passed a GVariant object from one of the g_variant_new*() functions, or from one of the g_variant_get*() and other getter functions mentioned above. One consequence is that if the constructor taking a pointer is passed a pointer which has already been passed to and is managed by another GvarHandle object, the user must call g_variant_ref() herself explicitly: but GVariant objects already owned by a GvarHandle should not normally be passed to another GvarHandle that way, as GvarHandles have a copy constructor and assignment operator which will increment the reference count automatically.
In other words, invoke the constructor taking a pointer only with a newly created GVariant object, or with a GVariant object directly handed out by a GVariant getter function or as the return value of a gio dbus method call, and everything else will take care of itself. In this respect, GvarHandles work the same way as conventional shared pointer implementations managing objects allocated on free store. The same applies to the reset() method.
Because glib and gio themselves increment the reference count of a GVariant object where they need to take ownership, an already-managed object held by a GvarHandle can safely be passed by pointer as the first argument of one of glib's g_variant_*() functions or as an argument to one of gio's dbus functions, and that is one of its intended usages. For that purpose, the pointer can be obtained by means of the operatorT*() type conversion operator (which returns the underlying pointer), or by explicitly calling the get() method to obtain the underlying pointer.
By automatically handling GVariant reference counts, GvarHandle makes GVariant objects exception-safe, and they also permit GVariant objects to be kept in standard C++ containers.
GVariant objects are thread safe, including their reference counts. This means that a GVariant object may be held by GvarHandles in containers in different threads, and accessed concurrently in those different threads.
Typical usage might be, for example, as follows:
gint32 a = 2;
gint32 b = 10;
"TwoInts",
g_variant_new("(ii)", a, b),
G_DBUS_CALL_FLAGS_NONE,
-1,
0,
0));
if (!result.get()) {
g_critical("Failed to execute method TwoInts");
execute_error_strategy();
}
else {
gchar** str_arr = g_variant_dup_strv(sa_variant, 0);
}
Further examples of the use of GvarHandle, see Using GVariant as an opaque data type
- Note
- This class is only available if glib >= 2.24.0 is installed.