GnuCash 2.4.99
gnc-gobject-utils.c
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 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines