]> Pileus Git - ~andy/gtk/blob - docs/refcounting.txt
stylecontext: Do invalidation on first resize container
[~andy/gtk] / docs / refcounting.txt
1 The Reference Counting Scheme of GDK an GTK+
2 ============================================
3
4 Each data structure that provides reference counting offers a bunch of
5 functions that follow these conventions:
6
7   *_new:      Create a new structure with a reference count of 1.
8   *_ref:      Increase ref count by one.
9   *_unref:    Decrease ref count by one.  If the count drops to zero,
10               run appropriate finalization code and free the memory.
11               For data structures with a _destroy function, it will be
12               invoked at this point, if the data structure is not
13               already in a destroyed state.
14
15 GtkObjects also provide the following functions:
16
17   *_destroy:  Render an object `unusable', but as long as there are
18               references to it, its allocated memory will not be freed.
19   *_sink:     Clear a GtkObjects `floating' state and decrement the
20               reference count by 1.
21
22 GdkWindow
23 ---------
24
25 A GdkWindow has to be explicitly destroyed with gdk_window_destroy.
26 This will send out a request to destroy this window and all its
27 children, and will decrement the ref_count of the GdkWindow by one.
28 Thus, it releases the initial reference created by gdk_window_new.
29
30 All GdkWindows are kept in a hash table to translate from their XId to
31 the actual structure and the pointer in the hash table is reflected in
32 the reference count.  When a DestroyNotify event is received for a
33 particular GdkWindow, it is removed from the hash table and the
34 ref_count is updated accordingly.
35
36 You can call gdk_window_destroy more than once on a particular
37 GdkWindow, it will only be destroyed when it hasn't been yet.  The
38 ref_count is *always* decremented, tho. Be careful.
39
40 Remark: When writing NO_WINDOW widgets, care should be taken about
41         proper referencing/unreferencing of the parent's GdkWindow
42         that is used by the widget.
43  
44 GdkPixmap
45 ---------
46
47 There is no gdk_pixmap_destroy function.  The Pixmap is destroyed when
48 the last reference to it vanishes.
49
50 GdkPixmaps are kept in the same hash table as GdkWindows but the
51 pointer in the hash table is *not* reflected in the ref_count.
52
53 This works only when Pixmaps never get XEvents.  I'm not sure if this
54 is the case.
55
56 GdkBitmap
57 ---------
58
59 A GdkBitmap is only another name for a special use of GdkPixmap.
60
61 GdkVisual
62 ---------
63
64 There are no *_new or *_destroy functions and the *_ref and *_unref
65 functions are no-ops.  GdkVisuals are static structures and thus do not
66 need reference counting.  The ref counting functions are only there
67 for extra defensive programming.
68
69 GdkColormap
70 -----------
71
72 Nothing special.  There is no gdk_colormap_destroy function.
73
74 GdkFont / GdkFontSet
75 --------------------
76
77 GdkFont and GdkFontSet are equivalent as far as ref counting is
78 concerned.  Use gdk_font_ref and gdk_font_unref for both.
79
80 There is no gdk_font_free or gdk_fontset_free function.
81
82 GtkAcceleratorTable
83 -------------------
84
85 There is no gtk_accelerator_table_destroy function.
86
87 GtkTooltips
88 -----------
89
90 There is no gtk_tooltips_destroy function.
91
92 GtkStyle
93 --------
94
95 There is no gtk_style_destroy function.
96
97 GtkObject
98 ---------
99
100 GtkObjects follow the usual ref_counting strategy, but with a twist.
101
102 They are created with a ref_count of 1.  GtkObjects are able to
103 run finalization code when the ref_count drops to zero but you cannot
104 register arbitrary signal handlers to run at finalization time.
105
106 There is also the old gtk_object_destroy function and the "destroy"
107 signal but they are somewhat independent from finalization.  Just as
108 stated at the top of this text, gtk_object_destroy merely renders an
109 object unusable.  When the object is a container widget for example,
110 it unrealizes that widget, removes all children and disconnects all
111 signal handlers.  The finalization code is different, it would for
112 example free associated memory for text strings and release the
113 attached style.
114
115 This is the biggest change.  Every widget must be revised to have a
116 proper "destroy" function, etc.  Such a destroy function will only
117 be called once and is expected to leave the widget in a minimal but
118 consistent state.  Widgets that have been "destroyed" but not yet
119 finalized are flagged with GTK_DESTROY.  The "finalization" function
120 is new and should perform last-minute cleanup actions, in contrast
121 to the destroy function it will not be emitted as signal though.
122 It can assume that the "destroy" function has been called as the
123 last function on this widget.
124
125 Essentially, the old "destroy" function has been split into a
126 "finalize" plus a "destroy" function.
127
128 It is not possible to create GtkObjects with a ref_count of 0
129 because the first ref/unref pair will destroy it unintentionally.
130
131 To be mostly backward compatible with existing practice, a GtkObject
132 leads a more complicated life than the other reference counted structures.
133
134 When a GtkObject is created, it starts out in a special state called
135 "floating" (this is the twist).  This means that it is alive and has a
136 reference to it, but the `owner' of this reference is not known.
137 There are certain `potential owners' that will adopt a floating
138 GtkObject.  For GtkWidgets the most common adopters are the parent
139 widget.
140
141 When you want to adopt a possibly floating GtkObject, you call
142 gtk_object_sink on it.  This clears the floating state of the
143 GtkObject and decrements the ref_count by one, if it has been floating
144 previously.  Once the floating state has been cleared, it will never
145 be set again.
146
147 All widgets that are part of the display are linked into a
148 parent/child tree.  The link from the parent to a child is reflected
149 in the ref_count of the child, but the link from the child to the
150 parent is not reflected in the ref_count of the parent.
151
152 Like a GtkObject, a GtkWidget is created with a ref_count of 1 and
153 initially flagged as `floating'.  As soon as it is added as a child to
154 a parent, the `floating' flag is cleared and never will be set again.
155 Not even when it is later unparented.  The act of clearing the
156 `floating' flag also decrements the ref_count of the widget by one.
157
158 When the widget is unparented, its underlying GdkWindow is destroyed
159 (when it has one), it loses its reference from the parent and
160 naturally the ref_count is decremented.
161
162 It is considered a bug if a widget still has a GdkWindow when it is
163 being freed.
164
165 Toplevel widgets, which don't have a `natural' parent, are adopted by
166 special registering functions.  Because the of the reference count that
167 is set by the registering functions, toplevel widgets will have to be
168 explicitly destroyed, with the exception of GtkMenus.  GtkMenus are a
169 special case of toplevel widgets in that they will be `attached' to and
170 `detached' from other widgets.  The act of attaching a GtkMenu to a
171 widget will be reflected in its reference count.  The act of detaching
172 a GtkMenu will revert that.  Therefore GtkMenus naturally get destroyed
173 and finalized once they are detached from their reference holder.
174
175 So, the typical career of a GtkWindow a GtMenu attached to a
176 GtkOptionMenu looks like this:
177
178   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
179   /* window is created with ref_count == 1.  It is not flagged as
180    * `floating' because it has already been registered as a toplevel
181    * widget.
182    */
183
184   option_menu = gtk_option_menu_new ();
185   /* option_menu->ref_count == 1 and it is flagged as `floating'.
186    */
187   
188   gtk_container_add (window, option_menu);
189   /* option_menu->ref_count still == 1, but it is no longer `floating'.
190    */
191   
192   menu = gtk_menu_new ();
193   /* menu->ref_count == 1 and it is flagged as `floating'.
194    */
195   
196   menu_item = gtk_menu_item_new_with_label ("Choose Me");
197   /* menu_item->ref_count == 1 and it is flagged as `floating'.
198    */
199
200   gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
201   /* menu_item->ref_count still == 1, but it is no longer `floating'.
202    */
203   
204   gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);
205   /* menu->ref_count still == 1, but it is no longer `floating'.
206    */
207
208   gtk_widget_show (menu_item);
209   gtk_widget_show (option_menu);
210   gtk_widget_show (window);
211
212   /* The widgets get their GdkWindows, nothing significant happens to
213    * the ref_counts.
214    */
215
216 Then, when the user wants to get rid of the window:
217
218   gtk_widget_destroy (window);
219
220   /* The GdkWindow of `window' and all its child GdkWindows are
221    * destroyed.
222    *
223    * window is unregistered from the toplevel list and its ref_count
224    * drops to zero.  The destroy code of `window' destroys `option_menu'.
225    *
226    * The destroy code of `option_menu' causes the `menu' to be detached
227    * from it and its reference count drops to zero.
228    *
229    * The destroy code of `menu' destroys `menu_item'.
230    *
231    * The destruction of `menu_item' removes it from its parent, the
232    * menu_item->ref_count drops to zero and `menu_item' is finalized (freed).
233    *
234    * Now `menu', `option_menu' and `window' will be destroyed and finalized,
235    * in this order, since the reference count of each is zero.
236    */
237
238
239 Taking care of proper referencing
240 ---------------------------------
241
242 There are some cases where referencing of widgets from outside the toolkit
243 (on the application side) is needed.
244 Once the application performs an operation on a widget that will cause
245 its reference count to drop, if it wants to take further actions on the
246 widget, it needs to hold a reference to it.
247
248 Example code sequences that require reference wraps:
249
250    /* gtk_container_remove() will unparent the child and therefore
251     * cause its reference count to be decremented by one.
252     */
253    g_object_ref (widget);
254    gtk_container_remove (container, widget);
255    /* without the reference count, the widget would have been destroyed here.
256    */
257    gtk_container_add (container, widget);
258    g_object_unref (widget);
259
260
261   /* all items in item_list need to be referenced
262    * before gtk_list_remove_items() is invoked.
263    * this is somewhat tricky as gtk_list_append_items/gtk_list_prepend_items/
264    * gtk_list_insert_items will take over the lists nodes.
265    * we therefore have an extra GSList `*slist' for later unreferencing.
266    */
267    slist = NULL;
268    for (list = item_list; list; list = list->next)
269    {
270      g_object_ref (GTK_WIDGET (list->data));
271      slist = g_slist_prepend (slist, list->data);
272    }
273    gtk_list_remove_items (list, item_list);
274    gtk_list_append_items (other_list, item_list);
275    /* gtk_list_prepend_items (other_list, item_list); */
276    /* gtk_list_insert_items (other_list, item_list, 3); */
277    while (slist)
278    {
279      GSList *tmp;
280      
281      tmp = slist;
282      slist = slist->next;
283      g_object_unref (GTK_WIDGET (tmp->data));
284      g_slist_free_1 (tmp);
285    }
286    
287    /* Alternatively to the removal above you could just use
288     * gtk_list_remove_items_no_unref() which will add the additional
289     * reference count to the widget.
290     */
291    gtk_list_remove_items_no_unref (list, item_list);
292    gtk_list_prepend_items (other_list, item_list);
293
294
295 Now a (hopefully) complete list of functions that require
296 wrappers similar to the examples above:
297
298 void       gtk_container_remove         (GtkContainer     *container,
299                                          GtkWidget        *widget);
300 void       gtk_list_remove_items        (GtkList          *list,
301                                          GList            *items);
302 void       gtk_tree_remove_items        (GtkTree          *tree,
303                                          GList            *items);
304 void       gtk_tree_item_remove_subtree (GtkTreeItem      *tree_item);
305 void       gtk_menu_item_remove_submenu (GtkMenuItem      *menu_item);
306 void       gtk_option_menu_remove_menu  (GtkOptionMenu    *option_menu);
307
308
309
310 Initial proposal:
311         - Marius Vollmer <mvo@zagadka.ping.de>
312
313 Some modifications/additions, "Taking care of proper referencing" and
314 reference counting solution for GtkMenus:
315         - Tim Janik <timj@gimp.org>