[Gtk-sharp-list] PATCH: speed up treeview and managed values
Ben Maurer
bmaurer@users.sourceforge.net
Sun, 15 Feb 2004 13:32:25 -0500
--=-3KqUR1XCmUOyBNguJfPx
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
Sorry, i forgot to cvs add my .c file, it is attached:
--=-3KqUR1XCmUOyBNguJfPx
Content-Disposition: attachment; filename=managedvalue.c
Content-Type: text/x-c; name=managedvalue.c; charset=UTF-8
Content-Transfer-Encoding: 7bit
/*
* managedvalue.c
*
* Copyright (C) 2004 Ben Maurer
*
* Authors:
* Ben Maurer <bmaurer@users.sf.net>
*/
/*
* This handles references to managed objects. The code here could
* have been implemented in C#, however it is not for performance
* reasons. Basically, the C# impl would incur two costs which are
* pretty high:
*
* * C#'s type safty means we have to box objects when we are
* storing them in the ref count table. Given that there is alot of
* refing and unrefing going on, we get tons of memory allocated
* which the GC ends up having to deal with.
* * The cost of invoking a delegate from the C world is very high.
* we are much better off with a classic pointer to a function.
*
* This design is intended to make refing and derefing a cheap operation
*
* In the real world, this means that when you have a managed value
* inside a GValue, it is very cheap to access it.
*/
#include <glib-object.h>
#define HASH_LOOKUP_INT(ht, key) GPOINTER_TO_INT (g_hash_table_lookup ((ht), (key)))
#define HASH_INSERT_INT(ht, key, val) g_hash_table_insert ((ht), (key), GINT_TO_POINTER (val))
typedef void (*GtkSharpManagedFreeFunc) (gpointer handle);
static gpointer increment_ref (gpointer handle);
static void deincrement_ref (gpointer handle);
void gtksharp_managed_value_notify_new (gpointer handle);
GType gtksharp_managed_value_init (GtkSharpManagedFreeFunc free);
static GHashTable* ref_table;
static GtkSharpManagedFreeFunc free_func;
static gpointer
increment_ref (gpointer handle)
{
g_return_val_if_fail (ref_table && free_func, handle);
HASH_INSERT_INT (ref_table, handle, HASH_LOOKUP_INT (ref_table, handle) + 1);
return handle;
}
static void
deincrement_ref (gpointer handle)
{
g_return_if_fail (ref_table && free_func);
gint new_ref_count = HASH_LOOKUP_INT (ref_table, handle) - 1;
if (! new_ref_count) {
g_hash_table_remove (ref_table, handle);
free_func (handle);
} else {
HASH_INSERT_INT (ref_table, handle, new_ref_count);
}
}
void
gtksharp_managed_value_notify_new (gpointer handle)
{
g_return_val_if_fail (ref_table && free_func, handle);
HASH_INSERT_INT (ref_table, handle, HASH_LOOKUP_INT (ref_table, handle) + 1);
}
GType
gtksharp_managed_value_get_type (GtkSharpManagedFreeFunc free)
{
g_assert (! ref_table && ! free_func);
free_func = free;
ref_table = g_hash_table_new (NULL, NULL);
return g_boxed_type_register_static ("GtkSharpValue", increment_ref, deincrement_ref);
}
--=-3KqUR1XCmUOyBNguJfPx--