[Gnucash-changes] Add functions for tracking GObject based items.
David Hampton
hampton at cvs.gnucash.org
Fri Jun 10 18:07:00 EDT 2005
Log Message:
-----------
Add functions for tracking GObject based items. To help find memory
leaks, if gnucash is compiled with --enable-ref-counts-dumps the
contents of this database will be dumped when gnucash quits.
Tags:
----
gnucash-gnome2-dev
Modified Files:
--------------
gnucash:
configure.in
gnucash/src/core-utils:
Makefile.am
Added Files:
-----------
gnucash/src/core-utils:
gnc-gobject-utils.c
gnc-gobject-utils.h
Revision Data
-------------
Index: configure.in
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/configure.in,v
retrieving revision 1.359.2.51
retrieving revision 1.359.2.52
diff -Lconfigure.in -Lconfigure.in -u -r1.359.2.51 -r1.359.2.52
--- configure.in
+++ configure.in
@@ -896,9 +896,14 @@
GNOME_COMPILE_WARNINGS
# Look for libgnomeui by pkg-config
- PKG_CHECK_MODULES(GNOME, libgnomeui-2.0 >= 2.4
- gtk+-2.0 >= 2.4)
+ PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.4)
+ AS_SCRUB_INCLUDE(GTK_CFLAGS)
+ AC_SUBST(GTK_CFLAGS)
+ AC_SUBST(GTK_LIBS)
+
+ PKG_CHECK_MODULES(GNOME, libgnomeui-2.0 >= 2.4)
AS_SCRUB_INCLUDE(GNOME_CFLAGS)
+
AC_SUBST(GNOME_CFLAGS)
AC_SUBST(GNOME_LIBS)
Index: Makefile.am
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/core-utils/Makefile.am,v
retrieving revision 1.7.4.2
retrieving revision 1.7.4.3
diff -Lsrc/core-utils/Makefile.am -Lsrc/core-utils/Makefile.am -u -r1.7.4.2 -r1.7.4.3
--- src/core-utils/Makefile.am
+++ src/core-utils/Makefile.am
@@ -4,13 +4,15 @@
libcore_utils_la_SOURCES = \
core-utils.c \
gnc-gconf-utils.c \
+ gnc-gobject-utils.c \
gnc-hooks.c
libcore_utils_la_LDFLAGS = -module
libcore_utils_la_LIBADD = \
${GLIB_LIBS} \
- ${GCONF_LIBS}
+ ${GCONF_LIBS} \
+ ${GTK_LIBS}
libgw_core_utils_la_SOURCES = \
gw-core-utils.c
@@ -23,6 +25,7 @@
noinst_HEADERS = \
core-utils.h \
gnc-gconf-utils.h \
+ gnc-gobject-utils.h \
gnc-hooks.h \
gw-core-utils.h
@@ -32,7 +35,8 @@
${G_WRAP_COMPILE_ARGS} \
${GUILE_INCS} \
${GLIB_CFLAGS} \
- ${GCONF_CFLAGS}
+ ${GCONF_CFLAGS} \
+ ${GTK_CFLAGS}
gwmoddir = ${GNC_GWRAP_LIBDIR}
gwmod_DATA = gw-core-utils-spec.scm gw-core-utils.scm
--- /dev/null
+++ src/core-utils/gnc-gobject-utils.c
@@ -0,0 +1,195 @@
+/*
+ * gnc-gobject-utils.h -- utility functions for working
+ * with GObjects
+ * Copyright (C) 2005 David Hampton <hampton at employees.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652
+ * Boston, MA 02111-1307, USA gnu at gnu.org
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include "gnc-gobject-utils.h"
+
+#include <gtk/gtk.h> // For gtk_main_quit(). Can't get this to work with
+ // a g_source attached to the main glib context.
+
+
+/************************************************************/
+/* Gconf Utilities */
+/************************************************************/
+
+
+/** Get a pointer to the hash table used by the tracking database. If
+ * the hash table doesn't exist, it will be created. If gnucash was
+ * compiled iwh --enable-ref-count-dumps, this funtion is also the
+ * point where the gnc_gobject_tracking_dump() function is registered
+ * to be called the GTK exits.
+ *
+ * @internal.
+ */
+static GHashTable*
+gnc_gobject_tracking_table (void)
+{
+ static GHashTable *singleton = NULL;
+
+ if (!singleton) {
+ singleton = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+#if DEBUG_REFERENCE_COUNTING
+ gtk_quit_add (0, (GtkFunction)gnc_gobject_tracking_dump, NULL);
+#endif
+ }
+ return singleton;
+}
+
+
+/** Dump a single object from the tracking database. This is an
+ * auxiliary function used by the gnc_gobject_tracking_dump()
+ * function. This function currently only dumps the object pointer
+ * and the reference count. It can be extended, if necessary, via
+ * object introspection.
+ *
+ * @internal.
+ */
+static void
+gnc_gobject_dump_gobject (GObject *object, const gchar *name)
+{
+ //printf("Enter %s: object %p, name %s\n", __FUNCTION__, object, name);
+ g_warning(" object %p, ref count %d", object, object->ref_count);
+ //printf("Leave %s:\n", __FUNCTION__);
+}
+
+
+/** Dump a single list of objects from the tracking database. This is
+ * an auxiliary function used by the gnc_gobject_tracking_dump()
+ * function.
+ *
+ * @internal.
+ */
+static gboolean
+gnc_gobject_dump_list (const gchar *name, GList *list, gpointer user_data)
+{
+ //printf("Enter %s: name %s, list %p\n", __FUNCTION__, name, list);
+ g_warning(" %d %s", g_list_length(list), name);
+ g_list_foreach(list, (GFunc)gnc_gobject_dump_gobject, (gpointer)name);
+ //printf("Leave %s:\n", __FUNCTION__);
+ return TRUE;
+}
+
+
+/** Dump the entire object tracking database via the g_log() family of
+ * functions. This function is only called when gnucash exits, and
+ * at that point all of the objects should have been removed from the
+ * database and freed. Any object remaining is the result of a
+ * memory/object leakage.
+ */
+void
+gnc_gobject_tracking_dump (void)
+{
+ GHashTable *table;
+
+ //printf("Enter %s:\n", __FUNCTION__);
+ table = gnc_gobject_tracking_table();
+
+ if (g_hash_table_size(table) > 0) {
+ g_warning("The following objects remain alive:");
+ g_hash_table_foreach_remove(table, (GHRFunc)gnc_gobject_dump_list, NULL);
+ }
+ //printf("Leave %s:\n", __FUNCTION__);
+}
+
+
+/** Tell gnucash to remember this object in the database.
+ */
+void
+gnc_gobject_tracking_remember (GObject *object, GObjectClass *klass)
+{
+ GHashTable *table;
+ GList *list;
+ const gchar *name;
+
+ g_return_if_fail(G_IS_OBJECT(object));
+
+ /* Little dance here to handle startup conditions. During object
+ * initialization the object type changes as each each parent class
+ * is initialized. The class passed to the initialization function
+ * is always the ultimate class of the object. */
+ if (klass == NULL)
+ klass = G_OBJECT_GET_CLASS(object);
+ name = g_type_name(G_TYPE_FROM_CLASS(klass));
+
+ //printf("Enter %s: object %p of type %s\n", __FUNCTION__, object, name);
+ table = gnc_gobject_tracking_table();
+ list = g_hash_table_lookup(table, name);
+
+ if (g_list_index(list, object) != -1) {
+ g_critical("Object %p is already in list of %s", object, name);
+ //printf("Leave %s: already in list\n", __FUNCTION__);
+ return;
+ }
+
+ list = g_list_append(list, object);
+ g_hash_table_insert(table, g_strdup(name), list);
+ //printf("Leave %s:\n", __FUNCTION__);
+}
+
+
+/** Tell gnucash to remember this object in the database.
+ */
+void
+gnc_gobject_tracking_forget (GObject *object)
+{
+ GHashTable *table;
+ GList *list;
+ const gchar *name;
+
+ g_return_if_fail(G_IS_OBJECT(object));
+
+ name = G_OBJECT_TYPE_NAME(object);
+ //printf("Enter %s: object %p of type %s\n", __FUNCTION__, object, name);
+ table = gnc_gobject_tracking_table();
+ list = g_hash_table_lookup(table, name);
+ if (!list) {
+ //printf("Leave %s: list for %s objects not found.\n", __FUNCTION__, name);
+ return;
+ }
+ list = g_list_remove(list, object);
+ if (list) {
+ g_hash_table_replace(table, g_strdup(name), list);
+ //printf("Leave %s: object removed.\n", __FUNCTION__);
+ } else {
+ g_hash_table_remove(table, name);
+ //printf("Leave %s: object and list removed.\n", __FUNCTION__);
+ }
+}
+
+
+/** Get a list of all known objects of a specified type.
+ */
+const GList *
+gnc_gobject_tracking_get_list (const gchar *name)
+{
+ GHashTable *table;
+ GList *list;
+
+ //printf("Enter %s: name %s\n", __FUNCTION__, name);
+ table = gnc_gobject_tracking_table();
+ list = g_hash_table_lookup(table, name);
+ //printf("Leave %s: list %p\n", __FUNCTION__, list);
+ return list;
+}
--- /dev/null
+++ src/core-utils/gnc-gobject-utils.h
@@ -0,0 +1,115 @@
+/*
+ * gnc-gobject-utils.h -- utility functions for working
+ * with GObjects
+ * Copyright (C) 2005 David Hampton <hampton at employees.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652
+ * Boston, MA 02111-1307, USA gnu at gnu.org
+ */
+
+/** @addtogroup GLib
+ @{ */
+/** @addtogroup Gobject
+ @{ */
+
+/** @file gnc-gobject-utils.h
+ * @brief Gobject helper routines.
+ * @author Copyright (C) 2005 David Hampton <hampton at employees.org>
+ *
+ * The APIs in this file are designed to provide additional
+ * functionality to GObjects, or to make it easier to use the Gobject
+ * system from within Gnucash.
+ */
+
+#ifndef GNC_GOBJECT_UTILS_H
+#define GNC_GOBJECT_UTILS_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+/** @name Gobject Tracking Functions
+ * @{
+ *
+ * This set of functions is used to maintain a "database" of objects
+ * that are built on top of a GObject (any level of nesting). This
+ * database is simply a hash table of lists. The hash table takes
+ * the object name as its key and returns a list of all objects of
+ * that type. The object is then added to, deleted from, or looked
+ * up in the list. The database can also be queried for a list of
+ * all objects of a specified type. This can be used to find
+ * pre-existing GncTreeModels, etc. (In this case performing a
+ * search for a specific object wouldn't help because the information
+ * being inspected is private to the object.)
+ *
+ * Any object added to this databasse during the execution of gnucash
+ * should be deleted from it before completion of the program. WHen
+ * the program shuts down, a list of all abjects still in the
+ * database will be dumped out to the logfile. This should help
+ * developers find memoty leaks in their code where an object is
+ * lost, or is not release because it gained an extra reference at
+ * some point during its lifetime.
+ */
+
+
+/** Tell gnucash to remember this object in the database.
+ *
+ * @param object The object to be tracked. This can be a fully or
+ * partially instantiated object.
+ *
+ * @param klass The class structure for the object. This argument
+ * may be NULL if a fully instantiated object is passed in as the
+ * first argument. If a partially instantiated object is provided
+ * (I.E. a parent class called this function) then this argument is
+ * required. This is necessary because the class of the object
+ * changes as each of the parent class is instantiated. The class
+ * structure, however, status constant and always reflects the fully
+ * instantiated object.
+ */
+void gnc_gobject_tracking_remember (GObject *object, GObjectClass *klass);
+
+/** Tell gnucash to drop this object from the database.
+ *
+ * @param object The object to be dropped.
+ */
+void gnc_gobject_tracking_forget (GObject *object);
+
+/** Get a list of all known objects of a specified type.
+ *
+ * @param name The type name of the objects to be found. This is the
+ * name used when the object type was initialized. If unknown, it
+ * can be found by calling G_OBJECT_TYPE_NAME(object).
+ *
+ * @return A GList of objects of the specified type. This list is
+ * owned by the tracking code and must not be modified by the caller.
+ */
+const GList *gnc_gobject_tracking_get_list (const gchar *name);
+
+
+/** Dump the entire object tracking database via the g_log() family of
+ * functions. This function is only called when gnucash exits, and
+ * at that point all of the objects should have been removed from the
+ * database and freed. Any object remaining is the result of a
+ * memory/object leakage.
+ */
+void gnc_gobject_tracking_dump (void);
+
+/** @} */
+
+
+#endif /* GNC_GOBJECT_UTILS_H */
+/** @} */
+/** @} */
More information about the gnucash-changes
mailing list