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