⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 refcounting.txt

📁 gtk是linux一款强大的夸平台的图形化开发工具
💻 TXT
字号:
The Reference Counting Scheme of GDK an GTK+============================================Each data structure that provides reference counting offers a bunch offunctions 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, it's 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 explicitely destroyed with gdk_window_destroy.This will send out a request to destroy this window and all itschildren, and will decrement the ref_count of the GdkWindow by one.Thus, it releases the inital reference created by gdk_window_new.All GdkWindows are kept in a hash table to translate from their XId tothe actual structure and the pointer in the hash table is reflected inthe reference count.  When a DestroyNotify event is received for aparticular GdkWindow, it is removed from the hash table and theref_count is updated accordingly.You can call gdk_window_destroy more than once on a particularGdkWindow, it will only be destroyed when it hasn't been yet.  Theref_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 whenthe last reference to it vanishes.GdkPixmaps are kept in the same hash table as GdkWindows but thepointer in the hash table is *not* reflected in the ref_count.This works only when Pixmaps never get XEvents.  I'm not sure if thisis 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 *_unreffunctions are noops.  GdkVisuals are static structures and thus do notneed reference counting.  The ref counting functions are only therefor 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 isconcerned.  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 torun finalization code when the ref_count drops to zero but you cannotregister 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 asstated at the top of this text, gtk_object_destroy merely renders anobject unusable.  When the object is a container widget for example,it unrealizes that widget, removes all children and disconnects allsignal handlers.  The finalization code is different, it would forexample free associated memory for text strings and release theattached style.This is the biggest change.  Every widget must be revised to have aproper "destroy" function, etc.  Such a destroy function will onlybe called once and is expected to leave the widget in a minimal butconsistent state.  Widgets that have been "destroyed" but not yetfinalized are flagged with GTK_DESTROY.  The "finalization" functionis new and should perform last-minute cleanup actions, in contrastto the destroy function it will not be emitted as signal though.It can assume that the "destroy" function has been called as thelast 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 0because the first ref/unref pair will destroy it unintentionally.To be mostly backward compatible with existing practice, a GtkObjectleads 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 areference to it, but the `owner' of this reference is not known.There are certain `potential owners' that will adopt a floatingGtkObject.  For GtkWidgets the most common adopters are the parentwidget.When you want to adopt a possibly floating GtkObject, you callgtk_object_sink on it.  This clears the floating state of theGtkObject and decrements the ref_count by one, if it has been floatingpreviously.  Once the floating state has been cleared, it will neverbe set again.All widgets that are part of the display are linked into aparent/child tree.  The link from the parent to a child is reflectedin the ref_count of the child, but the link from the child to theparent is not reflected in the ref_count of the parent.Like a GtkObject, a GtkWidget is created with a ref_count of 1 andinitially flagged as `floating'.  As soon as it is added as a child toa 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 andnaturally the ref_count is decremented.It is considered a bug if a widget still has a GdkWindow when it isbeing freed.Toplevel widgets, which don't have a `natural' parent, are adopted byspecial registering functions.  Because the of the reference count thatis set by the registering functions, toplevel widgets will have to beexplicitly destroyed, with the exception of GtkMenus.  GtkMenus are aspecial case of toplevel widgets in that they will be `attached' to and`detached' from other widgets.  The act of attaching a GtkMenu to awidget will be reflected in its reference count.  The act of detachinga GtkMenu will revert that.  Therefore GtkMenus naturally get destroyedand finalized once they are detached from their reference holder.So, the typical career of a GtkWindow a GtMenu attached to aGtkOptionMenu 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_append (GTK_MENU (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 loplevel list and its ref_count   * drops to zero.  The destroy code of `window' destroyes `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' destroyes `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 performes an operation on a widget that will causeits reference count to drop, if it wants to take further actions on thewidget, 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 it's reference count to be decremented by one.    */   gtk_widget_ref (widget);   gtk_container_remove (container, widget);   /* without the reference count, the widget would have been destroyed here.   */   gtk_container_add (container, widget);   gtk_widget_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)   {     gtk_widget_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;     gtk_widget_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 requirewrappers 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" andreference counting solution for GtkMenus:	- Tim Janik <timj@gimp.org>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -