docs: Remove old refcounting file
This references GTK+2-era objects, and isn't really useful anymore.
This commit is contained in:
		@ -1,315 +0,0 @@
 | 
			
		||||
The Reference Counting Scheme of GDK an GTK+
 | 
			
		||||
============================================
 | 
			
		||||
 | 
			
		||||
Each data structure that provides reference counting offers a bunch of
 | 
			
		||||
functions that follow these conventions:
 | 
			
		||||
 | 
			
		||||
  *_new:      Create a new structure with a reference count of 1.
 | 
			
		||||
  *_ref:      Increase ref count by one.
 | 
			
		||||
  *_unref:    Decrease ref count by one.  If the count drops to zero,
 | 
			
		||||
              run appropriate finalization code and free the memory.
 | 
			
		||||
	      For data structures with a _destroy function, it will be
 | 
			
		||||
	      invoked at this point, if the data structure is not
 | 
			
		||||
              already in a destroyed state.
 | 
			
		||||
 | 
			
		||||
GtkObjects also provide the following functions:
 | 
			
		||||
 | 
			
		||||
  *_destroy:  Render an object `unusable', but as long as there are
 | 
			
		||||
              references to it, its allocated memory will not be freed.
 | 
			
		||||
  *_sink:     Clear a GtkObjects `floating' state and decrement the
 | 
			
		||||
	      reference count by 1.
 | 
			
		||||
 | 
			
		||||
GdkWindow
 | 
			
		||||
---------
 | 
			
		||||
 | 
			
		||||
A GdkWindow has to be explicitly destroyed with gdk_window_destroy.
 | 
			
		||||
This will send out a request to destroy this window and all its
 | 
			
		||||
children, and will decrement the ref_count of the GdkWindow by one.
 | 
			
		||||
Thus, it releases the initial reference created by gdk_window_new.
 | 
			
		||||
 | 
			
		||||
All GdkWindows are kept in a hash table to translate from their XId to
 | 
			
		||||
the actual structure and the pointer in the hash table is reflected in
 | 
			
		||||
the reference count.  When a DestroyNotify event is received for a
 | 
			
		||||
particular GdkWindow, it is removed from the hash table and the
 | 
			
		||||
ref_count is updated accordingly.
 | 
			
		||||
 | 
			
		||||
You can call gdk_window_destroy more than once on a particular
 | 
			
		||||
GdkWindow, it will only be destroyed when it hasn't been yet.  The
 | 
			
		||||
ref_count is *always* decremented, tho. Be careful.
 | 
			
		||||
 | 
			
		||||
Remark: When writing NO_WINDOW widgets, care should be taken about
 | 
			
		||||
        proper referencing/unreferencing of the parent's GdkWindow
 | 
			
		||||
        that is used by the widget.
 | 
			
		||||
 
 | 
			
		||||
GdkPixmap
 | 
			
		||||
---------
 | 
			
		||||
 | 
			
		||||
There is no gdk_pixmap_destroy function.  The Pixmap is destroyed when
 | 
			
		||||
the last reference to it vanishes.
 | 
			
		||||
 | 
			
		||||
GdkPixmaps are kept in the same hash table as GdkWindows but the
 | 
			
		||||
pointer in the hash table is *not* reflected in the ref_count.
 | 
			
		||||
 | 
			
		||||
This works only when Pixmaps never get XEvents.  I'm not sure if this
 | 
			
		||||
is the case.
 | 
			
		||||
 | 
			
		||||
GdkBitmap
 | 
			
		||||
---------
 | 
			
		||||
 | 
			
		||||
A GdkBitmap is only another name for a special use of GdkPixmap.
 | 
			
		||||
 | 
			
		||||
GdkVisual
 | 
			
		||||
---------
 | 
			
		||||
 | 
			
		||||
There are no *_new or *_destroy functions and the *_ref and *_unref
 | 
			
		||||
functions are no-ops.  GdkVisuals are static structures and thus do not
 | 
			
		||||
need reference counting.  The ref counting functions are only there
 | 
			
		||||
for extra defensive programming.
 | 
			
		||||
 | 
			
		||||
GdkColormap
 | 
			
		||||
-----------
 | 
			
		||||
 | 
			
		||||
Nothing special.  There is no gdk_colormap_destroy function.
 | 
			
		||||
 | 
			
		||||
GdkFont / GdkFontSet
 | 
			
		||||
--------------------
 | 
			
		||||
 | 
			
		||||
GdkFont and GdkFontSet are equivalent as far as ref counting is
 | 
			
		||||
concerned.  Use gdk_font_ref and gdk_font_unref for both.
 | 
			
		||||
 | 
			
		||||
There is no gdk_font_free or gdk_fontset_free function.
 | 
			
		||||
 | 
			
		||||
GtkAcceleratorTable
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
There is no gtk_accelerator_table_destroy function.
 | 
			
		||||
 | 
			
		||||
GtkTooltips
 | 
			
		||||
-----------
 | 
			
		||||
 | 
			
		||||
There is no gtk_tooltips_destroy function.
 | 
			
		||||
 | 
			
		||||
GtkStyle
 | 
			
		||||
--------
 | 
			
		||||
 | 
			
		||||
There is no gtk_style_destroy function.
 | 
			
		||||
 | 
			
		||||
GtkObject
 | 
			
		||||
---------
 | 
			
		||||
 | 
			
		||||
GtkObjects follow the usual ref_counting strategy, but with a twist.
 | 
			
		||||
 | 
			
		||||
They are created with a ref_count of 1.  GtkObjects are able to
 | 
			
		||||
run finalization code when the ref_count drops to zero but you cannot
 | 
			
		||||
register arbitrary signal handlers to run at finalization time.
 | 
			
		||||
 | 
			
		||||
There is also the old gtk_object_destroy function and the "destroy"
 | 
			
		||||
signal but they are somewhat independent from finalization.  Just as
 | 
			
		||||
stated at the top of this text, gtk_object_destroy merely renders an
 | 
			
		||||
object unusable.  When the object is a container widget for example,
 | 
			
		||||
it unrealizes that widget, removes all children and disconnects all
 | 
			
		||||
signal handlers.  The finalization code is different, it would for
 | 
			
		||||
example free associated memory for text strings and release the
 | 
			
		||||
attached style.
 | 
			
		||||
 | 
			
		||||
This is the biggest change.  Every widget must be revised to have a
 | 
			
		||||
proper "destroy" function, etc.  Such a destroy function will only
 | 
			
		||||
be called once and is expected to leave the widget in a minimal but
 | 
			
		||||
consistent state.  Widgets that have been "destroyed" but not yet
 | 
			
		||||
finalized are flagged with GTK_DESTROY.  The "finalization" function
 | 
			
		||||
is new and should perform last-minute cleanup actions, in contrast
 | 
			
		||||
to the destroy function it will not be emitted as signal though.
 | 
			
		||||
It can assume that the "destroy" function has been called as the
 | 
			
		||||
last function on this widget.
 | 
			
		||||
 | 
			
		||||
Essentially, the old "destroy" function has been split into a
 | 
			
		||||
"finalize" plus a "destroy" function.
 | 
			
		||||
 | 
			
		||||
It is not possible to create GtkObjects with a ref_count of 0
 | 
			
		||||
because the first ref/unref pair will destroy it unintentionally.
 | 
			
		||||
 | 
			
		||||
To be mostly backward compatible with existing practice, a GtkObject
 | 
			
		||||
leads a more complicated life than the other reference counted structures.
 | 
			
		||||
 | 
			
		||||
When a GtkObject is created, it starts out in a special state called
 | 
			
		||||
"floating" (this is the twist).  This means that it is alive and has a
 | 
			
		||||
reference to it, but the `owner' of this reference is not known.
 | 
			
		||||
There are certain `potential owners' that will adopt a floating
 | 
			
		||||
GtkObject.  For GtkWidgets the most common adopters are the parent
 | 
			
		||||
widget.
 | 
			
		||||
 | 
			
		||||
When you want to adopt a possibly floating GtkObject, you call
 | 
			
		||||
gtk_object_sink on it.  This clears the floating state of the
 | 
			
		||||
GtkObject and decrements the ref_count by one, if it has been floating
 | 
			
		||||
previously.  Once the floating state has been cleared, it will never
 | 
			
		||||
be set again.
 | 
			
		||||
 | 
			
		||||
All widgets that are part of the display are linked into a
 | 
			
		||||
parent/child tree.  The link from the parent to a child is reflected
 | 
			
		||||
in the ref_count of the child, but the link from the child to the
 | 
			
		||||
parent is not reflected in the ref_count of the parent.
 | 
			
		||||
 | 
			
		||||
Like a GtkObject, a GtkWidget is created with a ref_count of 1 and
 | 
			
		||||
initially flagged as `floating'.  As soon as it is added as a child to
 | 
			
		||||
a parent, the `floating' flag is cleared and never will be set again.
 | 
			
		||||
Not even when it is later unparented.  The act of clearing the
 | 
			
		||||
`floating' flag also decrements the ref_count of the widget by one.
 | 
			
		||||
 | 
			
		||||
When the widget is unparented, its underlying GdkWindow is destroyed
 | 
			
		||||
(when it has one), it loses its reference from the parent and
 | 
			
		||||
naturally the ref_count is decremented.
 | 
			
		||||
 | 
			
		||||
It is considered a bug if a widget still has a GdkWindow when it is
 | 
			
		||||
being freed.
 | 
			
		||||
 | 
			
		||||
Toplevel widgets, which don't have a `natural' parent, are adopted by
 | 
			
		||||
special registering functions.  Because the of the reference count that
 | 
			
		||||
is set by the registering functions, toplevel widgets will have to be
 | 
			
		||||
explicitly destroyed, with the exception of GtkMenus.  GtkMenus are a
 | 
			
		||||
special case of toplevel widgets in that they will be `attached' to and
 | 
			
		||||
`detached' from other widgets.  The act of attaching a GtkMenu to a
 | 
			
		||||
widget will be reflected in its reference count.  The act of detaching
 | 
			
		||||
a GtkMenu will revert that.  Therefore GtkMenus naturally get destroyed
 | 
			
		||||
and finalized once they are detached from their reference holder.
 | 
			
		||||
 | 
			
		||||
So, the typical career of a GtkWindow a GtMenu attached to a
 | 
			
		||||
GtkOptionMenu looks like this:
 | 
			
		||||
 | 
			
		||||
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 | 
			
		||||
  /* window is created with ref_count == 1.  It is not flagged as
 | 
			
		||||
   * `floating' because it has already been registered as a toplevel
 | 
			
		||||
   * widget.
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  option_menu = gtk_option_menu_new ();
 | 
			
		||||
  /* option_menu->ref_count == 1 and it is flagged as `floating'.
 | 
			
		||||
   */
 | 
			
		||||
  
 | 
			
		||||
  gtk_container_add (window, option_menu);
 | 
			
		||||
  /* option_menu->ref_count still == 1, but it is no longer `floating'.
 | 
			
		||||
   */
 | 
			
		||||
  
 | 
			
		||||
  menu = gtk_menu_new ();
 | 
			
		||||
  /* menu->ref_count == 1 and it is flagged as `floating'.
 | 
			
		||||
   */
 | 
			
		||||
  
 | 
			
		||||
  menu_item = gtk_menu_item_new_with_label ("Choose Me");
 | 
			
		||||
  /* menu_item->ref_count == 1 and it is flagged as `floating'.
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
 | 
			
		||||
  /* menu_item->ref_count still == 1, but it is no longer `floating'.
 | 
			
		||||
   */
 | 
			
		||||
  
 | 
			
		||||
  gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);
 | 
			
		||||
  /* menu->ref_count still == 1, but it is no longer `floating'.
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  gtk_widget_show (menu_item);
 | 
			
		||||
  gtk_widget_show (option_menu);
 | 
			
		||||
  gtk_widget_show (window);
 | 
			
		||||
 | 
			
		||||
  /* The widgets get their GdkWindows, nothing significant happens to
 | 
			
		||||
   * the ref_counts.
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
Then, when the user wants to get rid of the window:
 | 
			
		||||
 | 
			
		||||
  gtk_widget_destroy (window);
 | 
			
		||||
 | 
			
		||||
  /* The GdkWindow of `window' and all its child GdkWindows are
 | 
			
		||||
   * destroyed.
 | 
			
		||||
   *
 | 
			
		||||
   * window is unregistered from the toplevel list and its ref_count
 | 
			
		||||
   * drops to zero.  The destroy code of `window' destroys `option_menu'.
 | 
			
		||||
   *
 | 
			
		||||
   * The destroy code of `option_menu' causes the `menu' to be detached
 | 
			
		||||
   * from it and its reference count drops to zero.
 | 
			
		||||
   *
 | 
			
		||||
   * The destroy code of `menu' destroys `menu_item'.
 | 
			
		||||
   *
 | 
			
		||||
   * The destruction of `menu_item' removes it from its parent, the
 | 
			
		||||
   * menu_item->ref_count drops to zero and `menu_item' is finalized (freed).
 | 
			
		||||
   *
 | 
			
		||||
   * Now `menu', `option_menu' and `window' will be destroyed and finalized,
 | 
			
		||||
   * in this order, since the reference count of each is zero.
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Taking care of proper referencing
 | 
			
		||||
---------------------------------
 | 
			
		||||
 | 
			
		||||
There are some cases where referencing of widgets from outside the toolkit
 | 
			
		||||
(on the application side) is needed.
 | 
			
		||||
Once the application performs an operation on a widget that will cause
 | 
			
		||||
its reference count to drop, if it wants to take further actions on the
 | 
			
		||||
widget, it needs to hold a reference to it.
 | 
			
		||||
 | 
			
		||||
Example code sequences that require reference wraps:
 | 
			
		||||
 | 
			
		||||
   /* gtk_container_remove() will unparent the child and therefore
 | 
			
		||||
    * cause its reference count to be decremented by one.
 | 
			
		||||
    */
 | 
			
		||||
   g_object_ref (widget);
 | 
			
		||||
   gtk_container_remove (container, widget);
 | 
			
		||||
   /* without the reference count, the widget would have been destroyed here.
 | 
			
		||||
   */
 | 
			
		||||
   gtk_container_add (container, widget);
 | 
			
		||||
   g_object_unref (widget);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  /* all items in item_list need to be referenced
 | 
			
		||||
   * before gtk_list_remove_items() is invoked.
 | 
			
		||||
   * this is somewhat tricky as gtk_list_append_items/gtk_list_prepend_items/
 | 
			
		||||
   * gtk_list_insert_items will take over the lists nodes.
 | 
			
		||||
   * we therefore have an extra GSList `*slist' for later unreferencing.
 | 
			
		||||
   */
 | 
			
		||||
   slist = NULL;
 | 
			
		||||
   for (list = item_list; list; list = list->next)
 | 
			
		||||
   {
 | 
			
		||||
     g_object_ref (GTK_WIDGET (list->data));
 | 
			
		||||
     slist = g_slist_prepend (slist, list->data);
 | 
			
		||||
   }
 | 
			
		||||
   gtk_list_remove_items (list, item_list);
 | 
			
		||||
   gtk_list_append_items (other_list, item_list);
 | 
			
		||||
   /* gtk_list_prepend_items (other_list, item_list); */
 | 
			
		||||
   /* gtk_list_insert_items (other_list, item_list, 3); */
 | 
			
		||||
   while (slist)
 | 
			
		||||
   {
 | 
			
		||||
     GSList *tmp;
 | 
			
		||||
     
 | 
			
		||||
     tmp = slist;
 | 
			
		||||
     slist = slist->next;
 | 
			
		||||
     g_object_unref (GTK_WIDGET (tmp->data));
 | 
			
		||||
     g_slist_free_1 (tmp);
 | 
			
		||||
   }
 | 
			
		||||
   
 | 
			
		||||
   /* Alternatively to the removal above you could just use
 | 
			
		||||
    * gtk_list_remove_items_no_unref() which will add the additional
 | 
			
		||||
    * reference count to the widget.
 | 
			
		||||
    */
 | 
			
		||||
   gtk_list_remove_items_no_unref (list, item_list);
 | 
			
		||||
   gtk_list_prepend_items (other_list, item_list);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Now a (hopefully) complete list of functions that require
 | 
			
		||||
wrappers similar to the examples above:
 | 
			
		||||
 | 
			
		||||
void       gtk_container_remove         (GtkContainer     *container,
 | 
			
		||||
                                         GtkWidget        *widget);
 | 
			
		||||
void       gtk_list_remove_items        (GtkList          *list,
 | 
			
		||||
                                         GList            *items);
 | 
			
		||||
void       gtk_tree_remove_items        (GtkTree          *tree,
 | 
			
		||||
                                         GList            *items);
 | 
			
		||||
void       gtk_tree_item_remove_subtree (GtkTreeItem      *tree_item);
 | 
			
		||||
void       gtk_menu_item_remove_submenu (GtkMenuItem      *menu_item);
 | 
			
		||||
void       gtk_option_menu_remove_menu  (GtkOptionMenu    *option_menu);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Initial proposal:
 | 
			
		||||
	- Marius Vollmer <mvo@zagadka.ping.de>
 | 
			
		||||
 | 
			
		||||
Some modifications/additions, "Taking care of proper referencing" and
 | 
			
		||||
reference counting solution for GtkMenus:
 | 
			
		||||
	- Tim Janik <timj@gimp.org>
 | 
			
		||||
		Reference in New Issue
	
	Block a user