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>
This commit is contained in:
parent
c603dc67ca
commit
5dc42284a5
5 changed files with 185 additions and 45 deletions
|
@ -84,6 +84,7 @@ static const int n_cogl_behavioural_debug_keys =
|
||||||
G_N_ELEMENTS (cogl_behavioural_debug_keys);
|
G_N_ELEMENTS (cogl_behavioural_debug_keys);
|
||||||
|
|
||||||
unsigned int _cogl_debug_flags[COGL_DEBUG_N_INTS];
|
unsigned int _cogl_debug_flags[COGL_DEBUG_N_INTS];
|
||||||
|
GHashTable *_cogl_debug_instances;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_parse_debug_string_for_keys (const char *value,
|
_cogl_parse_debug_string_for_keys (const char *value,
|
||||||
|
|
|
@ -75,6 +75,7 @@ typedef enum {
|
||||||
#define COGL_DEBUG_N_INTS COGL_FLAGS_N_INTS_FOR_SIZE (COGL_DEBUG_N_FLAGS)
|
#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 unsigned int _cogl_debug_flags[COGL_DEBUG_N_INTS];
|
||||||
|
extern GHashTable *_cogl_debug_instances;
|
||||||
|
|
||||||
#define COGL_DEBUG_ENABLED(flag) \
|
#define COGL_DEBUG_ENABLED(flag) \
|
||||||
COGL_FLAGS_GET (_cogl_debug_flags, flag)
|
COGL_FLAGS_GET (_cogl_debug_flags, flag)
|
||||||
|
|
|
@ -126,6 +126,26 @@ struct _CoglObject
|
||||||
#define COGL_OBJECT_COMMON_DEFINE_WITH_CODE(TypeName, type_name, code) \
|
#define COGL_OBJECT_COMMON_DEFINE_WITH_CODE(TypeName, type_name, code) \
|
||||||
\
|
\
|
||||||
static CoglObjectClass _cogl_##type_name##_class; \
|
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 \
|
GQuark \
|
||||||
_cogl_object_##type_name##_get_type (void) \
|
_cogl_object_##type_name##_get_type (void) \
|
||||||
|
@ -134,6 +154,16 @@ _cogl_object_##type_name##_get_type (void) \
|
||||||
if (!type) \
|
if (!type) \
|
||||||
{ \
|
{ \
|
||||||
type = g_quark_from_static_string ("Cogl"#TypeName); \
|
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; } \
|
{ code; } \
|
||||||
} \
|
} \
|
||||||
return type; \
|
return type; \
|
||||||
|
@ -149,7 +179,8 @@ static Cogl##TypeName * \
|
||||||
_cogl_##type_name##_object_new (Cogl##TypeName *new_obj) \
|
_cogl_##type_name##_object_new (Cogl##TypeName *new_obj) \
|
||||||
{ \
|
{ \
|
||||||
CoglObject *obj = (CoglObject *)&new_obj->_parent; \
|
CoglObject *obj = (CoglObject *)&new_obj->_parent; \
|
||||||
obj->ref_count = 1; \
|
obj->ref_count = 0; \
|
||||||
|
cogl_object_ref (obj); \
|
||||||
obj->n_user_data_entries = 0; \
|
obj->n_user_data_entries = 0; \
|
||||||
obj->user_data_array = NULL; \
|
obj->user_data_array = NULL; \
|
||||||
\
|
\
|
||||||
|
@ -157,9 +188,11 @@ _cogl_##type_name##_object_new (Cogl##TypeName *new_obj) \
|
||||||
if (!obj->klass->type) \
|
if (!obj->klass->type) \
|
||||||
{ \
|
{ \
|
||||||
obj->klass->type = _cogl_object_##type_name##_get_type (); \
|
obj->klass->type = _cogl_object_##type_name##_get_type (); \
|
||||||
obj->klass->virt_free = _cogl_##type_name##_free; \
|
obj->klass->virt_free = \
|
||||||
|
_cogl_object_##type_name##_indirect_free; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
_cogl_object_##type_name##_inc (); \
|
||||||
_COGL_OBJECT_DEBUG_NEW (TypeName, obj); \
|
_COGL_OBJECT_DEBUG_NEW (TypeName, obj); \
|
||||||
return new_obj; \
|
return new_obj; \
|
||||||
} \
|
} \
|
||||||
|
|
|
@ -247,3 +247,35 @@ cogl_object_get_user_data (CoglObject *object, CoglUserDataKey *key)
|
||||||
return NULL;
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -81,6 +81,37 @@ typedef struct
|
||||||
*/
|
*/
|
||||||
typedef void (*CoglUserDataDestroyCallback) (void *user_data);
|
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)
|
* cogl_object_set_user_data: (skip)
|
||||||
* @object: The object to associate private data with
|
* @object: The object to associate private data with
|
||||||
|
@ -123,5 +154,47 @@ cogl_object_set_user_data (CoglObject *object,
|
||||||
void *
|
void *
|
||||||
cogl_object_get_user_data (CoglObject *object,
|
cogl_object_get_user_data (CoglObject *object,
|
||||||
CoglUserDataKey *key);
|
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 */
|
#endif /* __COGL_OBJECT_H */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue