[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--