summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLionel Landwerlin <lionel.g.landwerlin@linux.intel.com>2011-06-10 18:44:09 +0100
committerNeil Roberts <neil@linux.intel.com>2011-06-14 12:14:02 +0100
commit5dc42284a5174d6cb451d0f5956801e67da3e627 (patch)
treee8a55ba7be83b7b710e318a2d5a8e95e0f867b23
parentc603dc67ca13d26e3909196500da693a92654dee (diff)
downloadcogl-5dc42284a5174d6cb451d0f5956801e67da3e627.tar.gz
cogl-debug: add instrumentation to track the number of objects
This allows to track the number of objects allocated by Cogl. The results are displayed on the standard output by calling : cogl_debug_print_instances (); Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@linux.intel.com> Signed-off-by: Neil Roberts <neil@linux.intel.com>
-rw-r--r--cogl/cogl-debug.c1
-rw-r--r--cogl/cogl-debug.h1
-rw-r--r--cogl/cogl-object-private.h123
-rw-r--r--cogl/cogl-object.c32
-rw-r--r--cogl/cogl-object.h73
5 files changed, 185 insertions, 45 deletions
diff --git a/cogl/cogl-debug.c b/cogl/cogl-debug.c
index 5b3ecc82..46ab5b4d 100644
--- a/cogl/cogl-debug.c
+++ b/cogl/cogl-debug.c
@@ -84,6 +84,7 @@ static const int n_cogl_behavioural_debug_keys =
G_N_ELEMENTS (cogl_behavioural_debug_keys);
unsigned int _cogl_debug_flags[COGL_DEBUG_N_INTS];
+GHashTable *_cogl_debug_instances;
static void
_cogl_parse_debug_string_for_keys (const char *value,
diff --git a/cogl/cogl-debug.h b/cogl/cogl-debug.h
index 294de846..292de259 100644
--- a/cogl/cogl-debug.h
+++ b/cogl/cogl-debug.h
@@ -75,6 +75,7 @@ typedef enum {
#define COGL_DEBUG_N_INTS COGL_FLAGS_N_INTS_FOR_SIZE (COGL_DEBUG_N_FLAGS)
extern unsigned int _cogl_debug_flags[COGL_DEBUG_N_INTS];
+extern GHashTable *_cogl_debug_instances;
#define COGL_DEBUG_ENABLED(flag) \
COGL_FLAGS_GET (_cogl_debug_flags, flag)
diff --git a/cogl/cogl-object-private.h b/cogl/cogl-object-private.h
index e8b4ed01..e4c450e4 100644
--- a/cogl/cogl-object-private.h
+++ b/cogl/cogl-object-private.h
@@ -123,51 +123,84 @@ struct _CoglObject
#define _COGL_HANDLE_DEBUG_UNREF _COGL_OBJECT_DEBUG_UNREF
#define COGL_HANDLE_DEBUG_FREE COGL_OBJECT_DEBUG_FREE
-#define COGL_OBJECT_COMMON_DEFINE_WITH_CODE(TypeName, type_name, code) \
- \
-static CoglObjectClass _cogl_##type_name##_class; \
- \
-GQuark \
-_cogl_object_##type_name##_get_type (void) \
-{ \
- static GQuark type = 0; \
- if (!type) \
- { \
- type = g_quark_from_static_string ("Cogl"#TypeName); \
- { code; } \
- } \
- return type; \
-} \
- \
-GQuark \
-_cogl_handle_##type_name##_get_type (void) \
-{ \
- return _cogl_object_##type_name##_get_type (); \
-} \
- \
-static Cogl##TypeName * \
-_cogl_##type_name##_object_new (Cogl##TypeName *new_obj) \
-{ \
- CoglObject *obj = (CoglObject *)&new_obj->_parent; \
- obj->ref_count = 1; \
- obj->n_user_data_entries = 0; \
- obj->user_data_array = NULL; \
- \
- obj->klass = &_cogl_##type_name##_class; \
- if (!obj->klass->type) \
- { \
- obj->klass->type = _cogl_object_##type_name##_get_type ();\
- obj->klass->virt_free = _cogl_##type_name##_free; \
- } \
- \
- _COGL_OBJECT_DEBUG_NEW (TypeName, obj); \
- return new_obj; \
-} \
- \
-Cogl##TypeName * \
-_cogl_##type_name##_pointer_from_handle (CoglHandle handle) \
-{ \
- return handle; \
+#define COGL_OBJECT_COMMON_DEFINE_WITH_CODE(TypeName, type_name, code) \
+ \
+static CoglObjectClass _cogl_##type_name##_class; \
+static unsigned long _cogl_object_##type_name##_count; \
+ \
+static inline void \
+_cogl_object_##type_name##_inc (void) \
+{ \
+ _cogl_object_##type_name##_count++; \
+} \
+ \
+static inline void \
+_cogl_object_##type_name##_dec (void) \
+{ \
+ _cogl_object_##type_name##_count--; \
+} \
+ \
+static void \
+_cogl_object_##type_name##_indirect_free (CoglObject *obj) \
+{ \
+ _cogl_##type_name##_free ((Cogl##TypeName *) obj); \
+ _cogl_object_##type_name##_dec (); \
+} \
+ \
+GQuark \
+_cogl_object_##type_name##_get_type (void) \
+{ \
+ static GQuark type = 0; \
+ if (!type) \
+ { \
+ type = g_quark_from_static_string ("Cogl"#TypeName); \
+ _cogl_object_##type_name##_count = 0; \
+ \
+ if (_cogl_debug_instances == NULL) \
+ _cogl_debug_instances = \
+ g_hash_table_new (g_str_hash, g_str_equal); \
+ \
+ g_hash_table_insert (_cogl_debug_instances, \
+ "Cogl"#TypeName, \
+ &_cogl_object_##type_name##_count); \
+ \
+ { code; } \
+ } \
+ return type; \
+} \
+ \
+GQuark \
+_cogl_handle_##type_name##_get_type (void) \
+{ \
+ return _cogl_object_##type_name##_get_type (); \
+} \
+ \
+static Cogl##TypeName * \
+_cogl_##type_name##_object_new (Cogl##TypeName *new_obj) \
+{ \
+ CoglObject *obj = (CoglObject *)&new_obj->_parent; \
+ obj->ref_count = 0; \
+ cogl_object_ref (obj); \
+ obj->n_user_data_entries = 0; \
+ obj->user_data_array = NULL; \
+ \
+ obj->klass = &_cogl_##type_name##_class; \
+ if (!obj->klass->type) \
+ { \
+ obj->klass->type = _cogl_object_##type_name##_get_type (); \
+ obj->klass->virt_free = \
+ _cogl_object_##type_name##_indirect_free; \
+ } \
+ \
+ _cogl_object_##type_name##_inc (); \
+ _COGL_OBJECT_DEBUG_NEW (TypeName, obj); \
+ return new_obj; \
+} \
+ \
+Cogl##TypeName * \
+_cogl_##type_name##_pointer_from_handle (CoglHandle handle) \
+{ \
+ return handle; \
}
#define COGL_OBJECT_DEFINE_WITH_CODE(TypeName, type_name, code) \
diff --git a/cogl/cogl-object.c b/cogl/cogl-object.c
index 90109eba..41800569 100644
--- a/cogl/cogl-object.c
+++ b/cogl/cogl-object.c
@@ -247,3 +247,35 @@ cogl_object_get_user_data (CoglObject *object, CoglUserDataKey *key)
return NULL;
}
+void
+cogl_debug_object_foreach_type (CoglDebugObjectForeachTypeCallback func,
+ void *user_data)
+{
+ GHashTableIter iter;
+ unsigned long *instance_count;
+ CoglDebugObjectTypeInfo info;
+
+ g_hash_table_iter_init (&iter, _cogl_debug_instances);
+ while (g_hash_table_iter_next (&iter,
+ (void *) &info.name,
+ (void *) &instance_count))
+ {
+ info.instance_count = *instance_count;
+ func (&info, user_data);
+ }
+}
+
+static void
+print_instances_cb (const CoglDebugObjectTypeInfo *info,
+ void *user_data)
+{
+ g_print ("\t%s: %lu\n", info->name, info->instance_count);
+}
+
+void
+cogl_debug_object_print_instances (void)
+{
+ g_print ("Cogl instances:\n");
+
+ cogl_debug_object_foreach_type (print_instances_cb, NULL);
+}
diff --git a/cogl/cogl-object.h b/cogl/cogl-object.h
index 71dd8bd7..f948c7f0 100644
--- a/cogl/cogl-object.h
+++ b/cogl/cogl-object.h
@@ -82,6 +82,37 @@ typedef struct
typedef void (*CoglUserDataDestroyCallback) (void *user_data);
/**
+ * CoglDebugObjectTypeInfo:
+ * @name: A human readable name for the type.
+ * @instance_count: The number of objects of this type that are
+ * currently in use
+ *
+ * This struct is used to pass information to the callback when
+ * cogl_debug_object_foreach_type() is called.
+ *
+ * Since: 1.8
+ * Stability: unstable
+ */
+typedef struct
+{
+ const char *name;
+ unsigned long instance_count;
+} CoglDebugObjectTypeInfo;
+
+/**
+ * CoglDebugObjectForeachTypeCallback:
+ * @info: A pointer to a struct containing information about the type.
+ *
+ * A callback function to use for cogl_debug_object_foreach_type().
+ *
+ * Since: 1.8
+ * Stability: unstable
+ */
+typedef void
+(* CoglDebugObjectForeachTypeCallback) (const CoglDebugObjectTypeInfo *info,
+ void *user_data);
+
+/**
* cogl_object_set_user_data: (skip)
* @object: The object to associate private data with
* @key: The address of a #CoglUserDataKey which provides a unique value
@@ -123,5 +154,47 @@ cogl_object_set_user_data (CoglObject *object,
void *
cogl_object_get_user_data (CoglObject *object,
CoglUserDataKey *key);
+
+#ifdef COGL_ENABLE_EXPERIMENTAL_API
+
+#define cogl_debug_object_foreach_type \
+ cogl_debug_object_foreach_type_EXP
+
+/**
+ * cogl_debug_object_foreach_type:
+ * func: A callback function for each type
+ * user_data: A pointer to pass to @func
+ *
+ * Invokes @func once for each type of object that Cogl uses and
+ * passes a count of the number of objects for that type. This is
+ * intended to be used solely for debugging purposes to track down
+ * issues with objects leaking.
+ *
+ * Since: 1.8
+ * Stability: unstable
+ */
+void
+cogl_debug_object_foreach_type (CoglDebugObjectForeachTypeCallback func,
+ void *user_data);
+
+#define cogl_debug_object_print_instances \
+ cogl_debug_object_print_instances_EXP
+
+/**
+ * cogl_debug_object_print_instances:
+ *
+ * Prints a list of all the object types that Cogl uses along with the
+ * number of objects of that type that are currently in use. This is
+ * intended to be used solely for debugging purposes to track down
+ * issues with objects leaking.
+ *
+ * Since: 1.8
+ * Stability: unstable
+ */
+void
+cogl_debug_object_print_instances (void);
+
+#endif /* COGL_ENABLE_EXPERIMENTAL_API */
+
#endif /* __COGL_OBJECT_H */