c++-gtk-utils
Public Member Functions | List of all members
Cgu::GvarHandle Class Reference

This is a handle for managing the reference count of GVariant objects. More...

#include <c++-gtk-utils/gvar_handle.h>

Public Member Functions

 GvarHandle (GVariant *ptr=0) noexcept
 
void reset (GVariant *ptr=0) noexcept
 
 GvarHandle (const GvarHandle &gvar) noexcept
 
 GvarHandle (GvarHandle &&gvar) noexcept
 
GvarHandleoperator= (const GvarHandle &gvar) noexcept
 
GvarHandleoperator= (GvarHandle &&gvar) noexcept
 
GVariant * get () const noexcept
 
 operator GVariant * () const noexcept
 
 ~GvarHandle ()
 

Detailed Description

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:

// execute a method "TwoInts" taking two 'int' arguments and
// returning a string-array via g_dbus_proxy_call_sync()
gint32 a = 2;
gint32 b = 10;
Cgu::GvarHandle result(g_dbus_proxy_call_sync(proxy,
"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 {
// gio's dbus implementation wraps all return
// values in a tuple: first extract the string-array
// from the tuple
Cgu::GvarHandle sa_variant(g_variant_get_child_value(result, 0));
// free str_arr with g_strfreev()
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.

Constructor & Destructor Documentation

◆ GvarHandle() [1/3]

Cgu::GvarHandle::GvarHandle ( GVariant *  ptr = 0)
inlineexplicitnoexcept

The constructor does not throw. g_variant_ref_sink() is called if the managed object has a floating reference.

Parameters
ptrThe GVariant object which the GvarHandle is to manage (if any).
Note
The pointer passed, if not NULL, should not normally already have been given to and so managed by any other GvarHandle object. Use the copy constructor instead instead in that case.

◆ GvarHandle() [2/3]

Cgu::GvarHandle::GvarHandle ( const GvarHandle gvar)
inlinenoexcept

The copy constructor does not throw. It increments the reference count of the managed object.

Parameters
gvarThe handle to be copied.

◆ GvarHandle() [3/3]

Cgu::GvarHandle::GvarHandle ( GvarHandle &&  gvar)
inlinenoexcept

The move constructor does not throw. It has move semantics.

Parameters
gvarThe handle to be moved.

◆ ~GvarHandle()

Cgu::GvarHandle::~GvarHandle ( )
inline

The destructor does not throw. It decrements the reference count of the managed object (if any), so destroying it if the reference count thereby becomes 0.

Member Function Documentation

◆ get()

GVariant* Cgu::GvarHandle::get ( ) const
inlinenoexcept

This method does not throw.

Returns
A pointer to the handled GVariant object (or NULL if none is handled).

◆ operator GVariant *()

Cgu::GvarHandle::operator GVariant * ( ) const
inlinenoexcept

This method does not throw.

Returns
A pointer to the handled GVariant object (or NULL if none is handled).

◆ operator=() [1/2]

GvarHandle& Cgu::GvarHandle::operator= ( const GvarHandle gvar)
inlinenoexcept

This method does not throw. It decrements the reference count of the former managed object (if any), so destroying it if the reference count thereby becomes 0, and increments the reference count of the new managed GVariant object.

Parameters
gvarThe assignor.
Returns
The GvarHandle object after assignment.

◆ operator=() [2/2]

GvarHandle& Cgu::GvarHandle::operator= ( GvarHandle &&  gvar)
inlinenoexcept

This method does not throw. It decrements the reference count of the former managed object (if any), so destroying it if the reference count thereby becomes 0, and has move semantics with respect to the new managed object.

Parameters
gvarThe handle to be moved.
Returns
The GvarHandle object after the move operation.

◆ reset()

void Cgu::GvarHandle::reset ( GVariant *  ptr = 0)
inlinenoexcept

Causes the handle to cease to manage its managed object (if any) and decrements its reference count, so destroying it if the reference count thereby becomes 0. If the argument passed is not NULL, the handle will manage the new GVariant object passed and g_variant_ref_sink() is called if the new object has a floating reference. This method does not throw.

Parameters
ptrNULL (the default), or a new GVariant object to manage.
Note
The pointer passed, if not NULL, should not normally already have been given to and so managed by any other GvarHandle object. Use the assignment operator instead in that case.

The documentation for this class was generated from the following file:
Cgu::GvarHandle
This is a handle for managing the reference count of GVariant objects.
Definition: gvar_handle.h:160