c++-gtk-utils
gvar_handle.h
Go to the documentation of this file.
1 /* Copyright (C) 2010 to 2013 Chris Vine
2 
3 The library comprised in this file or of which this file is part is
4 distributed by Chris Vine under the GNU Lesser General Public
5 License as follows:
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Lesser General Public License
9  as published by the Free Software Foundation; either version 2.1 of
10  the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Lesser General Public License, version 2.1, for more details.
16 
17  You should have received a copy of the GNU Lesser General Public
18  License, version 2.1, along with this library (see the file LGPL.TXT
19  which came with this source code package in the c++-gtk-utils
20  sub-directory); if not, write to the Free Software Foundation, Inc.,
21  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 
23 However, it is not intended that the object code of a program whose
24 source code instantiates a template from this file or uses macros or
25 inline functions (of any length) should by reason only of that
26 instantiation or use be subject to the restrictions of use in the GNU
27 Lesser General Public License. With that in mind, the words "and
28 macros, inline functions and instantiations of templates (of any
29 length)" shall be treated as substituted for the words "and small
30 macros and small inline functions (ten lines or less in length)" in
31 the fourth paragraph of section 5 of that licence. This does not
32 affect any other reason why object code may be subject to the
33 restrictions in that licence (nor for the avoidance of doubt does it
34 affect the application of section 2 of that licence to modifications
35 of the source code in this file).
36 
37 */
38 
39 #ifndef CGU_GVAR_HANDLE_H
40 #define CGU_GVAR_HANDLE_H
41 
42 #include <functional> // for std::less
43 
44 #include <glib.h>
45 
46 #if defined(DOXYGEN_PARSING) || GLIB_CHECK_VERSION(2,24,0)
47 
49 
50 /**
51  * @addtogroup handles handles and smart pointers
52  */
53 
54 namespace Cgu {
55 
56 /**
57  * @class GvarHandle gvar_handle.h c++-gtk-utils/gvar_handle.h
58  * @brief This is a handle for managing the reference count of
59  * GVariant objects.
60  * @ingroup handles
61  * @sa GobjHandle
62  *
63  * This is a class which manages the reference count of GVariant
64  * objects. It does not maintain its own reference count, but
65  * interfaces with that kept by the GVariant object. It is available
66  * since version 1.2.7.
67  *
68  * GVariant objects created with one of the g_variant_new*() functions
69  * are created with a floating reference. The constructor of a
70  * GvarHandle which takes a pointer will automatically take
71  * ownership of such a newly created GVariant object, by calling
72  * g_variant_ref_sink().
73  *
74  * GVariant objects which are obtained by one of the g_variant_get*()
75  * or similar getter functions, such as g_variant_get_child_value(),
76  * g_variant_get_variant(), g_variant_get() with a "v" or "(v)" format
77  * string, or g_variant_iter_next_value(), or as the return value of a
78  * dbus method call in gio's dbus implementation such as
79  * g_dbus_connection_call_sync(), g_dbus_connection_call_finish(),
80  * g_dbus_proxy_call_sync() or g_dbus_proxy_call_finish(), are not
81  * created with a floating reference (the variant normally already
82  * exists), but instead the reference count is incremented by the
83  * function concerned when the object is passed out to the user, so
84  * giving ownership to the user.
85  *
86  * It follows that g_variant_ref_sink() is not called by the
87  * constructor taking a pointer if the floating reference has already
88  * been sunk. This behaviour will ensure that the handle behaves the
89  * same whether it is passed a GVariant object from one of the
90  * g_variant_new*() functions, or from one of the g_variant_get*() and
91  * other getter functions mentioned above. One consequence is that if
92  * the constructor taking a pointer is passed a pointer which has
93  * already been passed to and is managed by another GvarHandle object,
94  * the user must call g_variant_ref() herself explicitly: but GVariant
95  * objects already owned by a GvarHandle should not normally be passed
96  * to another GvarHandle that way, as GvarHandles have a copy
97  * constructor and assignment operator which will increment the
98  * reference count automatically.
99  *
100  * In other words, invoke the constructor taking a pointer only with a
101  * newly created GVariant object, or with a GVariant object directly
102  * handed out by a GVariant getter function or as the return value of
103  * a gio dbus method call, and everything else will take care of
104  * itself. In this respect, GvarHandles work the same way as
105  * conventional shared pointer implementations managing objects
106  * allocated on free store. The same applies to the reset() method.
107  *
108  * Because glib and gio themselves increment the reference count of a
109  * GVariant object where they need to take ownership, an
110  * already-managed object held by a GvarHandle can safely be passed by
111  * pointer as the first argument of one of glib's g_variant_*()
112  * functions or as an argument to one of gio's dbus functions, and
113  * that is one of its intended usages. For that purpose, the pointer
114  * can be obtained by means of the operatorT*() type conversion
115  * operator (which returns the underlying pointer), or by explicitly
116  * calling the get() method to obtain the underlying pointer.
117  *
118  * By automatically handling GVariant reference counts, GvarHandle
119  * makes GVariant objects exception-safe, and they also permit
120  * GVariant objects to be kept in standard C++ containers.
121  *
122  * GVariant objects are thread safe, including their reference counts.
123  * This means that a GVariant object may be held by GvarHandles in
124  * containers in different threads, and accessed concurrently in those
125  * different threads.
126  *
127  * From version 1.2.12, the library provides ==, != and < comparison
128  * operators for GvarHandles, but only if the library is compiled with
129  * the \--with-smart-ptr-comp option, or if the user code defines the
130  * symbol CGU_USE_SMART_PTR_COMPARISON before gvar_handle.h is first
131  * parsed. This is because, if user code has provided such operators
132  * for these smart pointers itself, a duplicated function definition
133  * would arise.
134  *
135  * Typical usage might be, for example, as follows:
136  *
137  * @code
138  * // execute a method "TwoInts" taking two 'int' arguments and
139  * // returning a string-array via g_dbus_proxy_call_sync()
140  * gint32 a = 2;
141  * gint32 b = 10;
142  * Cgu::GvarHandle result(g_dbus_proxy_call_sync(proxy,
143  * "TwoInts",
144  * g_variant_new("(ii)", a, b),
145  * G_DBUS_CALL_FLAGS_NONE,
146  * -1,
147  * 0,
148  * 0));
149  * if (!result.get()) {
150  * g_critical("Failed to execute method TwoInts");
151  * execute_error_strategy();
152  * }
153  * else {
154  * // gio's dbus implementation wraps all return
155  * // values in a tuple: first extract the string-array
156  * // from the tuple
157  * Cgu::GvarHandle sa_variant(g_variant_get_child_value(result, 0));
158  * // free str_arr with g_strfreev()
159  * gchar** str_arr = g_variant_dup_strv(sa_variant, 0);
160  * }
161  * @endcode
162  *
163  * Further examples of the use of GvarHandle, see @ref Variants
164  *
165  * @note This class is only available if glib >= 2.24.0 is installed.
166  */
167 
168 class GvarHandle {
169 
170  GVariant* obj_p;
171 
172  void unreference() {
173  if (obj_p) g_variant_unref(obj_p);
174  }
175 
176  void reference() {
177  if (obj_p) g_variant_ref(obj_p);
178  }
179 
180 public:
181 
182  /**
183  * The constructor does not throw. g_variant_ref_sink() is called if
184  * the managed object has a floating reference.
185  * @param ptr The GVariant object which the GvarHandle is to manage
186  * (if any).
187  * @note The pointer passed, if not NULL, should not normally already
188  * have been given to and so managed by any other GvarHandle object.
189  * Use the copy constructor instead instead in that case.
190  *
191  * Since 1.2.7
192  */
193  explicit GvarHandle(GVariant* ptr = 0) {
194  obj_p = ptr;
195 
196  // if an object with a floating reference has been passed to this constructor,
197  // take ownership of it
198  if (ptr && g_variant_is_floating(ptr)) {
199  g_variant_ref_sink(ptr);
200  }
201  }
202 
203  /**
204  * Causes the handle to cease to manage its managed object (if any)
205  * and decrements its reference count, so destroying it if the
206  * reference count thereby becomes 0. If the argument passed is not
207  * NULL, the handle will manage the new GVariant object passed and
208  * g_variant_ref_sink() is called if the new object has a floating
209  * reference. This method does not throw.
210  * @param ptr NULL (the default), or a new GVariant object to manage.
211  * @note The pointer passed, if not NULL, should not normally already
212  * have been given to and so managed by any other GvarHandle object.
213  * Use the assignment operator instead in that case.
214  *
215  * Since 1.2.7
216  */
217  void reset(GVariant* ptr = 0) {
218 
219  unreference();
220  obj_p = ptr;
221 
222  // if an object with a floating reference has been passed to this method,
223  // take ownership of it
224  if (ptr && g_variant_is_floating(ptr)) {
225  g_variant_ref_sink(ptr);
226  }
227  }
228 
229  /**
230  * The copy constructor does not throw. It increments the reference
231  * count of the managed object.
232  * @param gvar The handle to be copied.
233  *
234  * Since 1.2.7
235  */
236  GvarHandle(const GvarHandle& gvar) {
237  obj_p = gvar.obj_p;
238  reference();
239  }
240 
241  /**
242  * This method does not throw. It decrements the reference count of
243  * the former managed object (if any), so destroying it if the
244  * reference count thereby becomes 0, and increments the reference
245  * count of the new managed GVariant object.
246  * @param gvar The assignor.
247  * @return The GvarHandle object after assignment.
248  *
249  * Since 1.2.7
250  */
252 
253  // check whether we are already referencing this object -
254  // if so make this a null op. This will also deal with
255  // self-assignment
256  if (obj_p != gvar.obj_p) {
257 
258  // first unreference any object referenced by this handle
259  unreference();
260 
261  // now inherit the GObject from the assigning handle
262  // and reference it
263  obj_p = gvar.obj_p;
264  reference();
265  }
266  return *this;
267  }
268 
269  /**
270  * This method does not throw.
271  * @return A pointer to the handled GVariant object (or NULL if none
272  * is handled).
273  *
274  * Since 1.2.7
275  */
276  GVariant* get() const {return obj_p;}
277 
278  /**
279  * This method does not throw.
280  * @return A pointer to the handled GVariant object (or NULL if none
281  * is handled).
282  *
283  * Since 1.2.7
284  */
285  operator GVariant*() const {return obj_p;}
286 
287  /**
288  * The destructor does not throw. It decrements the reference count
289  * of the managed object (if any), so destroying it if the reference
290  * count thereby becomes 0.
291  *
292  * Since 1.2.7
293  */
294  ~GvarHandle() {unreference();}
295 };
296 
297 #if defined(CGU_USE_SMART_PTR_COMPARISON) || defined(DOXYGEN_PARSING)
298 
299 // we can use built-in operator == when comparing pointers referencing
300 // different objects of the same type
301 /**
302  * @ingroup handles
303  *
304  * This comparison operator does not throw. It compares the addresses
305  * of the managed objects. This function is only available if the
306  * library is compiled with the \--with-smart-ptr-comp option, or if
307  * the user code defines the symbol CGU_USE_SMART_PTR_COMPARISON
308  * before gvar_handle.h is first parsed.
309  *
310  * Since 1.2.12
311  */
312 inline bool operator==(const GvarHandle& h1, const GvarHandle& h2) {
313  return (h1.get() == h2.get());
314 }
315 
316 /**
317  * @ingroup handles
318  *
319  * This comparison operator does not throw. It compares the addresses
320  * of the managed objects. This function is only available if the
321  * library is compiled with the \--with-smart-ptr-comp option, or if
322  * the user code defines the symbol CGU_USE_SMART_PTR_COMPARISON
323  * before gvar_handle.h is first parsed.
324  *
325  * Since 1.2.12
326  */
327 inline bool operator!=(const GvarHandle& h1, const GvarHandle& h2) {
328  return !(h1 == h2);
329 }
330 
331 // we must use std::less rather than the < built-in operator for
332 // pointers to objects not within the same array or object: "For
333 // templates greater, less, greater_equal, and less_equal, the
334 // specializations for any pointer type yield a total order, even if
335 // the built-in operators <, >, <=, >= do not." (para 20.3.3/8).
336 /**
337  * @ingroup handles
338  *
339  * This comparison operator does not throw unless std::less applied to
340  * pointer types throws (which it would not do with any sane
341  * implementation). It compares the addresses of the managed objects.
342  * This function is only available if the library is compiled with the
343  * \--with-smart-ptr-comp option, or if the user code defines the
344  * symbol CGU_USE_SMART_PTR_COMPARISON before gvar_handle.h is first
345  * parsed.
346  *
347  * Since 1.2.12
348  */
349 inline bool operator<(const GvarHandle& h1, const GvarHandle& h2) {
350  return std::less<GVariant*>()(h1.get(), h2.get());
351 }
352 
353 #endif // CGU_USE_SMART_PTR_COMPARISON
354 
355 } // namespace Cgu
356 
357 #else
358 #warning GvarHandle not available: glib >= 2.24.0 is required
359 #endif /*GLIB_CHECK_VERSION(2,24,0)*/
360 
361 #endif /*CGU_GVAR_HANDLE_H*/
Cgu::GvarHandle::operator=
GvarHandle & operator=(const GvarHandle &gvar)
Definition: gvar_handle.h:251
Cgu
Definition: application.h:45
Cgu::GvarHandle::reset
void reset(GVariant *ptr=0)
Definition: gvar_handle.h:217
Cgu::operator!=
bool operator!=(const GobjHandle< T > &h1, const GobjHandle< T > &h2)
Definition: gobj_handle.h:618
Cgu::operator<
bool operator<(const GobjHandle< T > &h1, const GobjHandle< T > &h2)
Definition: gobj_handle.h:641
Cgu::GvarHandle::GvarHandle
GvarHandle(GVariant *ptr=0)
Definition: gvar_handle.h:193
Cgu::GvarHandle::get
GVariant * get() const
Definition: gvar_handle.h:276
Cgu::GvarHandle::GvarHandle
GvarHandle(const GvarHandle &gvar)
Definition: gvar_handle.h:236
Cgu::GvarHandle::~GvarHandle
~GvarHandle()
Definition: gvar_handle.h:294
Cgu::operator==
bool operator==(const GobjHandle< T > &h1, const GobjHandle< T > &h2)
Definition: gobj_handle.h:602
Cgu::GvarHandle
This is a handle for managing the reference count of GVariant objects.
Definition: gvar_handle.h:168
cgu_config.h