|
GnuCash 2.4.99
|
00001 /* 00002 * gnc-gobject-utils.h -- utility functions for working 00003 * with GObjects 00004 * Copyright (C) 2005 David Hampton <hampton@employees.org> 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License as 00008 * published by the Free Software Foundation; either version 2 of 00009 * the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, contact: 00018 * 00019 * Free Software Foundation Voice: +1-617-542-5942 00020 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 00021 * Boston, MA 02110-1301, USA gnu@gnu.org 00022 */ 00023 00024 #include "config.h" 00025 00026 #include <stdio.h> 00027 #include "gnc-gobject-utils.h" 00028 00029 #include <gtk/gtk.h> // For gtk_main_quit(). Can't get this to work with 00030 // a g_source attached to the main glib context. 00031 00032 00033 static void gnc_gobject_weak_cb (gpointer user_data, GObject *object); 00034 00035 /************************************************************/ 00036 /* Gconf Utilities */ 00037 /************************************************************/ 00038 00039 00048 static GHashTable* 00049 gnc_gobject_tracking_table (void) 00050 { 00051 static GHashTable *singleton = NULL; 00052 00053 if (!singleton) 00054 { 00055 singleton = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); 00056 #if DEBUG_REFERENCE_COUNTING 00057 gtk_quit_add (0, (GtkFunction)gnc_gobject_tracking_dump, NULL); 00058 #endif 00059 } 00060 return singleton; 00061 } 00062 00063 00072 static void 00073 gnc_gobject_dump_gobject (GObject *object, const gchar *name) 00074 { 00075 //printf("Enter %s: object %p, name %s\n", G_STRFUNC, object, name); 00076 g_message(" object %p, ref count %d", object, object->ref_count); 00077 //printf("Leave %s:\n", G_STRFUNC); 00078 } 00079 00080 00087 static gboolean 00088 gnc_gobject_dump_list (const gchar *name, GList *list, gpointer user_data) 00089 { 00090 //printf("Enter %s: name %s, list %p\n", G_STRFUNC, name, list); 00091 g_message(" %d %s", g_list_length(list), name); 00092 g_list_foreach(list, (GFunc)gnc_gobject_dump_gobject, (gpointer)name); 00093 //printf("Leave %s:\n", G_STRFUNC); 00094 return TRUE; 00095 } 00096 00097 00104 void 00105 gnc_gobject_tracking_dump (void) 00106 { 00107 GHashTable *table; 00108 00109 //printf("Enter %s:\n", G_STRFUNC); 00110 table = gnc_gobject_tracking_table(); 00111 00112 if (g_hash_table_size(table) > 0) 00113 { 00114 g_message("The following objects remain alive:"); 00115 g_hash_table_foreach_remove(table, (GHRFunc)gnc_gobject_dump_list, NULL); 00116 } 00117 //printf("Leave %s:\n", G_STRFUNC); 00118 } 00119 00120 00123 void 00124 gnc_gobject_tracking_remember (GObject *object, GObjectClass *klass) 00125 { 00126 GHashTable *table; 00127 GList *list; 00128 const gchar *name; 00129 00130 g_return_if_fail(G_IS_OBJECT(object)); 00131 00132 /* Little dance here to handle startup conditions. During object 00133 * initialization the object type changes as each each parent class 00134 * is initialized. The class passed to the initialization function 00135 * is always the ultimate class of the object. */ 00136 if (klass == NULL) 00137 klass = G_OBJECT_GET_CLASS(object); 00138 name = g_type_name(G_TYPE_FROM_CLASS(klass)); 00139 00140 //printf("Enter %s: object %p of type %s\n", G_STRFUNC, object, name); 00141 table = gnc_gobject_tracking_table(); 00142 list = g_hash_table_lookup(table, name); 00143 00144 if (g_list_index(list, object) != -1) 00145 { 00146 g_critical("Object %p is already in list of %s", object, name); 00147 //printf("Leave %s: already in list\n", G_STRFUNC); 00148 return; 00149 } 00150 00151 list = g_list_append(list, object); 00152 g_hash_table_insert(table, g_strdup(name), list); 00153 00154 g_object_weak_ref(object, gnc_gobject_weak_cb, NULL); 00155 //printf("Leave %s:\n", G_STRFUNC); 00156 } 00157 00158 00159 static gboolean 00160 gnc_gobject_tracking_forget_internal (GObject *object) 00161 { 00162 GHashTable *table; 00163 GList *list, *item; 00164 const gchar *name; 00165 00166 g_return_val_if_fail(G_IS_OBJECT(object), FALSE); 00167 00168 name = G_OBJECT_TYPE_NAME(object); 00169 //printf("Enter %s: object %p of type %s\n", G_STRFUNC, object, name); 00170 table = gnc_gobject_tracking_table(); 00171 list = g_hash_table_lookup(table, name); 00172 if (!list) 00173 { 00174 //printf("Leave %s: list for %s objects not found.\n", G_STRFUNC, name); 00175 return FALSE; 00176 } 00177 00178 item = g_list_find(list, object); 00179 if (!item) 00180 { 00181 //printf("Leave %s: object %p not in %s object list.\n", G_STRFUNC, 00182 // object, name); 00183 return FALSE; 00184 } 00185 00186 list = g_list_remove_link(list, item); 00187 if (list) 00188 { 00189 g_hash_table_replace(table, g_strdup(name), list); 00190 //printf("Leave %s: object removed.\n", G_STRFUNC); 00191 } 00192 else 00193 { 00194 g_hash_table_remove(table, name); 00195 //printf("Leave %s: object and list removed.\n", G_STRFUNC); 00196 } 00197 return TRUE; 00198 } 00199 00200 00203 void 00204 gnc_gobject_tracking_forget (GObject *object) 00205 { 00206 if (gnc_gobject_tracking_forget_internal(object)) 00207 g_object_weak_unref(object, gnc_gobject_weak_cb, NULL); 00208 } 00209 00210 00220 static void 00221 gnc_gobject_weak_cb (gpointer user_data, GObject *object) 00222 { 00223 gnc_gobject_tracking_forget_internal(object); 00224 } 00225 00226 00229 const GList * 00230 gnc_gobject_tracking_get_list (const gchar *name) 00231 { 00232 GHashTable *table; 00233 GList *list; 00234 00235 //printf("Enter %s: name %s\n", G_STRFUNC, name); 00236 table = gnc_gobject_tracking_table(); 00237 list = g_hash_table_lookup(table, name); 00238 //printf("Leave %s: list %p\n", G_STRFUNC, list); 00239 return list; 00240 }
1.7.4