00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025
00026 #include <stdio.h>
00027 #include "gnc-gobject-utils.h"
00028
00029 #include <gtk/gtk.h>
00030
00031
00032
00033 static void gnc_gobject_weak_cb (gpointer user_data, GObject *object);
00034
00035
00036
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
00076 g_message(" object %p, ref count %d", object, object->ref_count);
00077
00078 }
00079
00080
00087 static gboolean
00088 gnc_gobject_dump_list (const gchar *name, GList *list, gpointer user_data)
00089 {
00090
00091 g_message(" %d %s", g_list_length(list), name);
00092 g_list_foreach(list, (GFunc)gnc_gobject_dump_gobject, (gpointer)name);
00093
00094 return TRUE;
00095 }
00096
00097
00104 void
00105 gnc_gobject_tracking_dump (void)
00106 {
00107 GHashTable *table;
00108
00109
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
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
00133
00134
00135
00136 if (klass == NULL)
00137 klass = G_OBJECT_GET_CLASS(object);
00138 name = g_type_name(G_TYPE_FROM_CLASS(klass));
00139
00140
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
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
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
00170 table = gnc_gobject_tracking_table();
00171 list = g_hash_table_lookup(table, name);
00172 if (!list)
00173 {
00174
00175 return FALSE;
00176 }
00177
00178 item = g_list_find(list, object);
00179 if (!item)
00180 {
00181
00182
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
00191 }
00192 else
00193 {
00194 g_hash_table_remove(table, name);
00195
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
00236 table = gnc_gobject_tracking_table();
00237 list = g_hash_table_lookup(table, name);
00238
00239 return list;
00240 }