template<class T>
class Cgu::GobjWeakHandle< T >
This is a handle for managing weak references to GObjects.
- See also
- GobjHandle
This class tracks a GObject, so that if that GObject no longer exists then operator bool() or the valid() method will return false, but does not take a strong reference by incrementing the reference count to the GObject and so take ownership of it. It has two main use areas: first, in order to break reference cycles that may otherwise arise if two classes would otherwise hold strong references to each other. Secondly, to manage a pointer to a GObject returned by a GTK+ getter function where ownership is not passed (that is, where the user is not expected to call g_object_unref() when finished with the return value). A typical example of this is the GtkTreeSelection object returned by gtk_tree_view_get_selection(). The GtkTreeSelection object is part of the GtkTreeView's implemention and will become invalid as soon as the GtkTreeView object is finalized.
As in the case of the GobjHandle class, although this class has operator*() and operator->() dereferencing operators, and so has normal smart pointer functionality, as it is intended for use with the normal C GObject/pango/GTK+ interfaces, ordinary use would involve passing the handle to a function taking a pointer 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.
Typical usage is as follows:
gtk_tree_selection_set_mode(s, GTK_SELECTION_SINGLE);
...
[some code blocks later]
if (s) {
GtkTreeIter iter;
GtkTreeModel* model = 0;
gtk_tree_selection_get_selected(s, &model, &iter);
...
}
else [report error];
Or instead of an 'if' block, GobjWeakHandleError could be caught:
gtk_tree_selection_set_mode(s, GTK_SELECTION_SINGLE);
...
[some code blocks later]
GtkTreeIter iter;
GtkTreeModel* model = 0;
try {
gtk_tree_selection_get_selected(s, &model, &iter);
...
}
Thread-safe use
This class wraps g_object_add_weak_pointer()/g_object_remove_weak_pointer(), and as those GObject functions have practical limitations concerning thread-safe use, this class has the same practical limitations. As shown above, typical usage for a weak pointer 's' would be 'if (s) do_it(s)', but if the thread calling that sequence (thread A) were not the thread controlling the lifetime of the referenced GObject (thread B), then thread B may have destroyed the GObject between thread A testing 's' and then calling the referenced object. The same applies to the test leading to GobjWeakHandleError being thrown.
In other words, in the GtkTreeSelection code example above, if the thread calling gtk_tree_selection_get_selected() were not the main GUI thread (which would anyway require the use of gdk_threads_enter()/gdk_threads_leave()), then the calling thread must ensure that the main GUI thread does not destroy the relevant tree view, and so the GtkTreeSelection object, from the beginning of the 'if' test to the end of the 'if' block, or for the duration of the try block. (This cannot be done just by incrementing the reference count of the tree view or the tree selection in the calling thread before the 'if' test or the try block is entered, because by the time the reference is incremented and the weak pointer tested, the tree view and tree selection may already be in their dispose functions but the tree selection's dispose function may not yet have reached the point of dispatching the callback NULLing the weak pointer. As a general design issue, it is usually best only to call GTK+ functions in one thread, and in order to make that straightforward, this library contains a number of classes and functions for inter-thread communication.)