From: Tim Janik Date: Thu, 17 Sep 1998 04:59:41 +0000 (+0000) Subject: implemented g_datalist_* along the lines of g_dataset, but operates on an X-Git-Url: http://git.openbox.org/?a=commitdiff_plain;h=ea4b8e4c02c19f6a997f28403ee78fe92dcf291b;p=dana%2Fcg-glib.git implemented g_datalist_* along the lines of g_dataset, but operates on an Thu Sep 17 06:36:25 1998 Tim Janik * glib.h: * gdataset.c: implemented g_datalist_* along the lines of g_dataset, but operates on an opaque gpointer *datalist; pointer, e.g. for the implementation of GtkObject named data. we cache a certain portion of the already freed data entries now, to gain a slight performance improve with data reallocation. Thu Sep 17 06:34:22 1998 Tim Janik * gmodule.h: * gmodule.c: implemented g_module_make_resident() which can be used to make modules resident. fixed a buglet about the optional "g_module_de_init" function in modules, which could get invoked twice on very obscure occasions. --- diff --git a/ChangeLog b/ChangeLog index fe05aa0c..aa9282ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Thu Sep 17 06:36:25 1998 Tim Janik + + * glib.h: + * gdataset.c: implemented g_datalist_* along the lines of g_dataset, + but operates on an opaque gpointer *datalist; pointer, e.g. for the + implementation of GtkObject named data. + we cache a certain portion of the already freed data entries now, to + gain a slight performance improve with data reallocation. + Tue Sep 15 14:57:30 1998 Owen Taylor * Makefile.am glib-config.in l*: Update to libtool-1.2b, diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index fe05aa0c..aa9282ef 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,12 @@ +Thu Sep 17 06:36:25 1998 Tim Janik + + * glib.h: + * gdataset.c: implemented g_datalist_* along the lines of g_dataset, + but operates on an opaque gpointer *datalist; pointer, e.g. for the + implementation of GtkObject named data. + we cache a certain portion of the already freed data entries now, to + gain a slight performance improve with data reallocation. + Tue Sep 15 14:57:30 1998 Owen Taylor * Makefile.am glib-config.in l*: Update to libtool-1.2b, diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index fe05aa0c..aa9282ef 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,12 @@ +Thu Sep 17 06:36:25 1998 Tim Janik + + * glib.h: + * gdataset.c: implemented g_datalist_* along the lines of g_dataset, + but operates on an opaque gpointer *datalist; pointer, e.g. for the + implementation of GtkObject named data. + we cache a certain portion of the already freed data entries now, to + gain a slight performance improve with data reallocation. + Tue Sep 15 14:57:30 1998 Owen Taylor * Makefile.am glib-config.in l*: Update to libtool-1.2b, diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index fe05aa0c..aa9282ef 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,12 @@ +Thu Sep 17 06:36:25 1998 Tim Janik + + * glib.h: + * gdataset.c: implemented g_datalist_* along the lines of g_dataset, + but operates on an opaque gpointer *datalist; pointer, e.g. for the + implementation of GtkObject named data. + we cache a certain portion of the already freed data entries now, to + gain a slight performance improve with data reallocation. + Tue Sep 15 14:57:30 1998 Owen Taylor * Makefile.am glib-config.in l*: Update to libtool-1.2b, diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index fe05aa0c..aa9282ef 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,12 @@ +Thu Sep 17 06:36:25 1998 Tim Janik + + * glib.h: + * gdataset.c: implemented g_datalist_* along the lines of g_dataset, + but operates on an opaque gpointer *datalist; pointer, e.g. for the + implementation of GtkObject named data. + we cache a certain portion of the already freed data entries now, to + gain a slight performance improve with data reallocation. + Tue Sep 15 14:57:30 1998 Owen Taylor * Makefile.am glib-config.in l*: Update to libtool-1.2b, diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index fe05aa0c..aa9282ef 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,12 @@ +Thu Sep 17 06:36:25 1998 Tim Janik + + * glib.h: + * gdataset.c: implemented g_datalist_* along the lines of g_dataset, + but operates on an opaque gpointer *datalist; pointer, e.g. for the + implementation of GtkObject named data. + we cache a certain portion of the already freed data entries now, to + gain a slight performance improve with data reallocation. + Tue Sep 15 14:57:30 1998 Owen Taylor * Makefile.am glib-config.in l*: Update to libtool-1.2b, diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index fe05aa0c..aa9282ef 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,12 @@ +Thu Sep 17 06:36:25 1998 Tim Janik + + * glib.h: + * gdataset.c: implemented g_datalist_* along the lines of g_dataset, + but operates on an opaque gpointer *datalist; pointer, e.g. for the + implementation of GtkObject named data. + we cache a certain portion of the already freed data entries now, to + gain a slight performance improve with data reallocation. + Tue Sep 15 14:57:30 1998 Owen Taylor * Makefile.am glib-config.in l*: Update to libtool-1.2b, diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index fe05aa0c..aa9282ef 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,12 @@ +Thu Sep 17 06:36:25 1998 Tim Janik + + * glib.h: + * gdataset.c: implemented g_datalist_* along the lines of g_dataset, + but operates on an opaque gpointer *datalist; pointer, e.g. for the + implementation of GtkObject named data. + we cache a certain portion of the already freed data entries now, to + gain a slight performance improve with data reallocation. + Tue Sep 15 14:57:30 1998 Owen Taylor * Makefile.am glib-config.in l*: Update to libtool-1.2b, diff --git a/gdataset.c b/gdataset.c index 85f0b7f1..904d31ab 100644 --- a/gdataset.c +++ b/gdataset.c @@ -24,17 +24,18 @@ /* --- defines --- */ -#define G_DATASET_BLOCK_SIZE (512) -#define G_DATASET_MEM_CHUNK_PREALLOC (64) -#define G_DATASET_DATA_MEM_CHUNK_PREALLOC (128) +#define G_QUARK_BLOCK_SIZE (512) +#define G_DATA_MEM_CHUNK_PREALLOC (128) +#define G_DATA_CACHE_MAX (512) +#define G_DATASET_MEM_CHUNK_PREALLOC (32) /* --- structures --- */ -typedef struct _GDatasetData GDatasetData; +typedef struct _GData GData; typedef struct _GDataset GDataset; -struct _GDatasetData +struct _GData { - GDatasetData *next; + GData *next; guint id; gpointer data; GDestroyNotify destroy_func; @@ -43,15 +44,21 @@ struct _GDatasetData struct _GDataset { gconstpointer location; - GDatasetData *data_list; + gpointer datalist; }; /* --- prototypes --- */ -static inline GDataset* g_dataset_lookup (gconstpointer dataset_location); -static inline void g_dataset_destroy_i (GDataset *dataset); -static void g_dataset_initialize (void); -static inline GQuark g_quark_new (const gchar *string); +static inline GDataset* g_dataset_lookup (gconstpointer dataset_location); +static inline void g_datalist_clear_i (gpointer *datalist); +static void g_dataset_destroy_internal (GDataset *dataset); +static inline void g_data_set_internal (gpointer *datalist, + GQuark key_id, + gpointer data, + GDestroyNotify destroy_func, + GDataset *d_dataset); +static void g_data_initialize (void); +static inline GQuark g_quark_new (const gchar *string); /* --- variables --- */ @@ -61,11 +68,52 @@ static GQuark g_quark_seq_id = 0; static GHashTable *g_dataset_location_ht = NULL; static GDataset *g_dataset_cached = NULL; static GMemChunk *g_dataset_mem_chunk = NULL; -static GMemChunk *g_dataset_data_mem_chunk = NULL; - +static GMemChunk *g_data_mem_chunk = NULL; +static GData *g_data_cache = NULL; +static guint g_data_cache_length = 0; /* --- functions --- */ +static inline void +g_datalist_clear_i (gpointer *datalist) +{ + register GData *list; + + /* unlink *all* items before walking their destructors + */ + list = *datalist; + *datalist = NULL; + + while (list) + { + register GData *prev; + + prev = list; + list = prev->next; + + if (prev->destroy_func) + prev->destroy_func (prev->data); + + if (g_data_cache_length < G_DATA_CACHE_MAX) + { + prev->next = g_data_cache; + g_data_cache = prev; + g_data_cache_length++; + } + else + g_mem_chunk_free (g_data_mem_chunk, prev); + } +} + +void +g_datalist_clear (gpointer *datalist) +{ + g_return_if_fail (datalist != NULL); + + while (*datalist) + g_datalist_clear_i (datalist); +} + static inline GDataset* g_dataset_lookup (gconstpointer dataset_location) { @@ -74,9 +122,6 @@ g_dataset_lookup (gconstpointer dataset_location) if (g_dataset_cached && g_dataset_cached->location == dataset_location) return g_dataset_cached; - if (!g_dataset_location_ht) - g_dataset_initialize (); - dataset = g_hash_table_lookup (g_dataset_location_ht, dataset_location); if (dataset) g_dataset_cached = dataset; @@ -84,30 +129,19 @@ g_dataset_lookup (gconstpointer dataset_location) return dataset; } -static inline void -g_dataset_destroy_i (GDataset *dataset) +static void +g_dataset_destroy_internal (GDataset *dataset) { - register GDatasetData *list; + gpointer datalist; if (dataset == g_dataset_cached) g_dataset_cached = NULL; g_hash_table_remove (g_dataset_location_ht, dataset->location); - list = dataset->data_list; + datalist = dataset->datalist; g_mem_chunk_free (g_dataset_mem_chunk, dataset); - while (list) - { - register GDatasetData *prev; - - prev = list; - list = prev->next; - - if (prev->destroy_func) - prev->destroy_func (prev->data); - - g_mem_chunk_free (g_dataset_data_mem_chunk, prev); - } + g_datalist_clear_i (&datalist); } void @@ -117,91 +151,27 @@ g_dataset_destroy (gconstpointer dataset_location) g_return_if_fail (dataset_location != NULL); - dataset = g_dataset_lookup (dataset_location); - if (dataset) - g_dataset_destroy_i (dataset); -} - -void -g_dataset_id_set_destroy (gconstpointer dataset_location, - GQuark key_id, - GDestroyNotify destroy_func) -{ - g_return_if_fail (dataset_location != NULL); - - if (key_id) - { - register GDataset *dataset; - - dataset = g_dataset_lookup (dataset_location); - if (dataset) - { - register GDatasetData *list; - - list = dataset->data_list; - while (list) - { - if (list->id == key_id) - { - list->destroy_func = destroy_func; - return; - } - } - } - } -} - -gpointer -g_dataset_id_get_data (gconstpointer dataset_location, - GQuark key_id) -{ - g_return_val_if_fail (dataset_location != NULL, NULL); - - if (key_id) + if (g_dataset_location_ht) { - register GDataset *dataset; - dataset = g_dataset_lookup (dataset_location); if (dataset) - { - register GDatasetData *list; - - for (list = dataset->data_list; list; list = list->next) - if (list->id == key_id) - return list->data; - } + g_dataset_destroy_internal (dataset); } - - return NULL; } -void -g_dataset_id_set_data_full (gconstpointer dataset_location, - GQuark key_id, - gpointer data, - GDestroyNotify destroy_func) +static inline void +g_data_set_internal (gpointer *datalist, + GQuark key_id, + gpointer data, + GDestroyNotify destroy_func, + GDataset *d_dataset) { - register GDataset *dataset; - register GDatasetData *list; - - g_return_if_fail (dataset_location != NULL); - g_return_if_fail (key_id > 0); + register GData *list; - dataset = g_dataset_lookup (dataset_location); - if (!dataset) - { - dataset = g_chunk_new (GDataset, g_dataset_mem_chunk); - dataset->location = dataset_location; - dataset->data_list = NULL; - g_hash_table_insert (g_dataset_location_ht, - (gpointer) dataset->location, /* Yuck */ - dataset); - } - - list = dataset->data_list; + list = *datalist; if (!data) { - register GDatasetData *prev; + register GData *prev; prev = NULL; while (list) @@ -212,19 +182,30 @@ g_dataset_id_set_data_full (gconstpointer dataset_location, prev->next = list->next; else { - dataset->data_list = list->next; + *datalist = list->next; - if (!dataset->data_list) - g_dataset_destroy_i (dataset); + /* the dataset destruction *must* be done + * prior to invokation of the data destroy function + */ + if (!*datalist && d_dataset) + g_dataset_destroy_internal (d_dataset); } - /* we need to have unlinked before invoking the destroy function + /* the GData struct *must* already be unlinked + * when invoking the destroy function */ if (list->destroy_func) list->destroy_func (list->data); - g_mem_chunk_free (g_dataset_data_mem_chunk, list); - + if (g_data_cache_length < G_DATA_CACHE_MAX) + { + list->next = g_data_cache; + g_data_cache = list; + g_data_cache_length++; + } + else + g_mem_chunk_free (g_data_mem_chunk, list); + return; } @@ -238,37 +219,198 @@ g_dataset_id_set_data_full (gconstpointer dataset_location, { if (list->id == key_id) { - register GDestroyNotify dfunc; - register gpointer ddata; - - dfunc = list->destroy_func; - ddata = list->data; - list->data = data; - list->destroy_func = destroy_func; + if (!list->destroy_func) + { + list->data = data; + list->destroy_func = destroy_func; + } + else + { + register GDestroyNotify dfunc; + register gpointer ddata; + + dfunc = list->destroy_func; + ddata = list->data; + list->data = data; + list->destroy_func = destroy_func; + + /* we need to have updated all structures prior to + * invokation of the destroy function + */ + dfunc (ddata); + } - /* we need to have updated all structures prior to - * invokation of the destroy function - */ - if (dfunc) - dfunc (ddata); - return; } list = list->next; } - list = g_chunk_new (GDatasetData, g_dataset_data_mem_chunk); - list->next = dataset->data_list; + if (g_data_cache) + { + list = g_data_cache; + g_data_cache = list->next; + g_data_cache_length--; + } + else + list = g_chunk_new (GData, g_data_mem_chunk); + list->next = *datalist; list->id = key_id; list->data = data; list->destroy_func = destroy_func; - dataset->data_list = list; + *datalist = list; + } +} + +void +g_dataset_id_set_data_full (gconstpointer dataset_location, + GQuark key_id, + gpointer data, + GDestroyNotify destroy_func) +{ + register GDataset *dataset; + + g_return_if_fail (dataset_location != NULL); + if (!key_id) + { + if (data) + g_return_if_fail (key_id > 0); + else + return; + } + + if (!g_dataset_location_ht) + g_data_initialize (); + + dataset = g_dataset_lookup (dataset_location); + if (!dataset) + { + dataset = g_chunk_new (GDataset, g_dataset_mem_chunk); + dataset->location = dataset_location; + dataset->datalist = NULL; + g_hash_table_insert (g_dataset_location_ht, + (gpointer) dataset->location, + dataset); + } + + g_data_set_internal (&dataset->datalist, key_id, data, destroy_func, dataset); +} + +void +g_datalist_id_set_data_full (gpointer *datalist, + GQuark key_id, + gpointer data, + GDestroyNotify destroy_func) +{ + g_return_if_fail (datalist != NULL); + if (!key_id) + { + if (data) + g_return_if_fail (key_id > 0); + else + return; + } + + g_data_set_internal (datalist, key_id, data, destroy_func, NULL); +} + +void +g_dataset_id_set_destroy (gconstpointer dataset_location, + GQuark key_id, + GDestroyNotify destroy_func) +{ + register GDataset *dataset; + + g_return_if_fail (dataset_location != NULL); + g_return_if_fail (key_id > 0); + + if (g_dataset_location_ht) + { + dataset = g_dataset_lookup (dataset_location); + if (dataset) + { + register GData *list; + + for (list = dataset->datalist; list; list = list->next) + if (list->id == key_id) + { + list->destroy_func = destroy_func; + break; + } + } + } +} + +void +g_datalist_id_set_destroy (gpointer *datalist, + GQuark key_id, + GDestroyNotify destroy_func) +{ + register GData *list; + + g_return_if_fail (datalist != NULL); + g_return_if_fail (key_id > 0); + + for (list = *datalist; list; list = list->next) + if (list->id == key_id) + { + list->destroy_func = destroy_func; + break; + } +} + +gpointer +g_dataset_id_get_data (gconstpointer dataset_location, + GQuark key_id) +{ + g_return_val_if_fail (dataset_location != NULL, NULL); + + if (key_id && g_dataset_location_ht) + { + register GDataset *dataset; + + dataset = g_dataset_lookup (dataset_location); + if (dataset) + { + register GData *list; + + for (list = dataset->datalist; list; list = list->next) + if (list->id == key_id) + return list->data; + } } + + return NULL; +} + +gpointer +g_datalist_id_get_data (gpointer *datalist, + GQuark key_id) +{ + g_return_val_if_fail (datalist != NULL, NULL); + + if (key_id) + { + register GData *list; + + for (list = *datalist; list; list = list->next) + if (list->id == key_id) + return list->data; + } + + return NULL; +} + +void +g_datalist_init (gpointer *datalist) +{ + g_return_if_fail (datalist != NULL); + + *datalist = NULL; } static void -g_dataset_initialize (void) +g_data_initialize (void) { if (!g_dataset_location_ht) { @@ -280,10 +422,10 @@ g_dataset_initialize (void) sizeof (GDataset), sizeof (GDataset) * G_DATASET_MEM_CHUNK_PREALLOC, G_ALLOC_AND_FREE); - g_dataset_data_mem_chunk = - g_mem_chunk_new ("GDatasetData MemChunk", - sizeof (GDatasetData), - sizeof (GDatasetData) * G_DATASET_DATA_MEM_CHUNK_PREALLOC, + g_data_mem_chunk = + g_mem_chunk_new ("GData MemChunk", + sizeof (GData), + sizeof (GData) * G_DATA_MEM_CHUNK_PREALLOC, G_ALLOC_AND_FREE); } } @@ -307,7 +449,7 @@ g_quark_from_string (const gchar *string) g_return_val_if_fail (string != NULL, 0); if (!g_quark_ht) - g_dataset_initialize (); + g_data_initialize (); quark = (gulong) g_hash_table_lookup (g_quark_ht, string); if (!quark) @@ -324,7 +466,7 @@ g_quark_from_static_string (const gchar *string) g_return_val_if_fail (string != NULL, 0); if (!g_quark_ht) - g_dataset_initialize (); + g_data_initialize (); quark = (gulong) g_hash_table_lookup (g_quark_ht, string); if (!quark) @@ -347,9 +489,9 @@ g_quark_new (const gchar *string) { GQuark quark; - if (g_quark_seq_id % G_DATASET_BLOCK_SIZE == 0) + if (g_quark_seq_id % G_QUARK_BLOCK_SIZE == 0) g_quarks = g_realloc (g_quarks, - (g_quark_seq_id + G_DATASET_BLOCK_SIZE) * sizeof (gchar*)); + (g_quark_seq_id + G_QUARK_BLOCK_SIZE) * sizeof (gchar*)); g_quarks[g_quark_seq_id] = (gchar*) string; diff --git a/glib.h b/glib.h index f4d738b3..0512e8b6 100644 --- a/glib.h +++ b/glib.h @@ -1441,7 +1441,36 @@ GQuark g_quark_from_string (const gchar *string); gchar* g_quark_to_string (GQuark quark); -/* Location Associated Data +/* Keyed Data List + */ +void g_datalist_init (gpointer *datalist); +void g_datalist_clear (gpointer *datalist); +gpointer g_datalist_id_get_data (gpointer *datalist, + GQuark key_id); +void g_datalist_id_set_data_full (gpointer *datalist, + GQuark key_id, + gpointer data, + GDestroyNotify destroy_func); +void g_datalist_id_set_destroy (gpointer *datalist, + GQuark key_id, + GDestroyNotify destroy_func); +#define g_datalist_id_set_data(dl, q, d) \ + g_datalist_id_set_data_full ((dl), (q), (d), NULL) +#define g_datalist_id_remove_data(dl, q) \ + g_datalist_id_set_data ((dl), (q), NULL) +#define g_datalist_get_data(dl, k) \ + (g_datalist_id_get_data ((dl), g_quark_try_string ((k)))) +#define g_datalist_set_data_full(dl, k, d, f) \ + g_datalist_id_set_data_full ((dl), g_quark_from_string ((k)), (d), (f)) +#define g_datalist_set_destroy(dl, k, f) \ + g_datalist_id_set_destroy ((dl), g_quark_try_string ((k)), (f)) +#define g_datalist_set_data(dl, k, d) \ + g_datalist_set_data_full ((dl), (k), (d), NULL) +#define g_datalist_remove_data(dl, k) \ + g_datalist_id_set_data ((dl), g_quark_try_string ((k)), NULL) + + +/* Location Associated Keyed Data */ void g_dataset_destroy (gconstpointer dataset_location); gpointer g_dataset_id_get_data (gconstpointer dataset_location, @@ -1458,15 +1487,15 @@ void g_dataset_id_set_destroy (gconstpointer dataset_location, #define g_dataset_id_remove_data(l, k) \ g_dataset_id_set_data ((l), (k), NULL) #define g_dataset_get_data(l, k) \ - (g_dataset_id_get_data ((l), g_quark_try_string (k))) + (g_dataset_id_get_data ((l), g_quark_try_string ((k)))) #define g_dataset_set_data_full(l, k, d, f) \ - g_dataset_id_set_data_full ((l), g_quark_from_string (k), (d), (f)) + g_dataset_id_set_data_full ((l), g_quark_from_string ((k)), (d), (f)) #define g_dataset_set_destroy(l, k, f) \ - g_dataset_id_set_destroy ((l), g_quark_from_string (k), (f)) + g_dataset_id_set_destroy ((l), g_quark_try_string ((k)), (f)) #define g_dataset_set_data(l, k, d) \ g_dataset_set_data_full ((l), (k), (d), NULL) -#define g_dataset_remove_data(l,k) \ - g_dataset_set_data ((l), (k), NULL) +#define g_dataset_remove_data(l, k) \ + g_dataset_id_set_data ((l), g_quark_try_string ((k)), NULL) /* GScanner: Flexible lexical scanner for general purpose. diff --git a/glib/gdataset.c b/glib/gdataset.c index 85f0b7f1..904d31ab 100644 --- a/glib/gdataset.c +++ b/glib/gdataset.c @@ -24,17 +24,18 @@ /* --- defines --- */ -#define G_DATASET_BLOCK_SIZE (512) -#define G_DATASET_MEM_CHUNK_PREALLOC (64) -#define G_DATASET_DATA_MEM_CHUNK_PREALLOC (128) +#define G_QUARK_BLOCK_SIZE (512) +#define G_DATA_MEM_CHUNK_PREALLOC (128) +#define G_DATA_CACHE_MAX (512) +#define G_DATASET_MEM_CHUNK_PREALLOC (32) /* --- structures --- */ -typedef struct _GDatasetData GDatasetData; +typedef struct _GData GData; typedef struct _GDataset GDataset; -struct _GDatasetData +struct _GData { - GDatasetData *next; + GData *next; guint id; gpointer data; GDestroyNotify destroy_func; @@ -43,15 +44,21 @@ struct _GDatasetData struct _GDataset { gconstpointer location; - GDatasetData *data_list; + gpointer datalist; }; /* --- prototypes --- */ -static inline GDataset* g_dataset_lookup (gconstpointer dataset_location); -static inline void g_dataset_destroy_i (GDataset *dataset); -static void g_dataset_initialize (void); -static inline GQuark g_quark_new (const gchar *string); +static inline GDataset* g_dataset_lookup (gconstpointer dataset_location); +static inline void g_datalist_clear_i (gpointer *datalist); +static void g_dataset_destroy_internal (GDataset *dataset); +static inline void g_data_set_internal (gpointer *datalist, + GQuark key_id, + gpointer data, + GDestroyNotify destroy_func, + GDataset *d_dataset); +static void g_data_initialize (void); +static inline GQuark g_quark_new (const gchar *string); /* --- variables --- */ @@ -61,11 +68,52 @@ static GQuark g_quark_seq_id = 0; static GHashTable *g_dataset_location_ht = NULL; static GDataset *g_dataset_cached = NULL; static GMemChunk *g_dataset_mem_chunk = NULL; -static GMemChunk *g_dataset_data_mem_chunk = NULL; - +static GMemChunk *g_data_mem_chunk = NULL; +static GData *g_data_cache = NULL; +static guint g_data_cache_length = 0; /* --- functions --- */ +static inline void +g_datalist_clear_i (gpointer *datalist) +{ + register GData *list; + + /* unlink *all* items before walking their destructors + */ + list = *datalist; + *datalist = NULL; + + while (list) + { + register GData *prev; + + prev = list; + list = prev->next; + + if (prev->destroy_func) + prev->destroy_func (prev->data); + + if (g_data_cache_length < G_DATA_CACHE_MAX) + { + prev->next = g_data_cache; + g_data_cache = prev; + g_data_cache_length++; + } + else + g_mem_chunk_free (g_data_mem_chunk, prev); + } +} + +void +g_datalist_clear (gpointer *datalist) +{ + g_return_if_fail (datalist != NULL); + + while (*datalist) + g_datalist_clear_i (datalist); +} + static inline GDataset* g_dataset_lookup (gconstpointer dataset_location) { @@ -74,9 +122,6 @@ g_dataset_lookup (gconstpointer dataset_location) if (g_dataset_cached && g_dataset_cached->location == dataset_location) return g_dataset_cached; - if (!g_dataset_location_ht) - g_dataset_initialize (); - dataset = g_hash_table_lookup (g_dataset_location_ht, dataset_location); if (dataset) g_dataset_cached = dataset; @@ -84,30 +129,19 @@ g_dataset_lookup (gconstpointer dataset_location) return dataset; } -static inline void -g_dataset_destroy_i (GDataset *dataset) +static void +g_dataset_destroy_internal (GDataset *dataset) { - register GDatasetData *list; + gpointer datalist; if (dataset == g_dataset_cached) g_dataset_cached = NULL; g_hash_table_remove (g_dataset_location_ht, dataset->location); - list = dataset->data_list; + datalist = dataset->datalist; g_mem_chunk_free (g_dataset_mem_chunk, dataset); - while (list) - { - register GDatasetData *prev; - - prev = list; - list = prev->next; - - if (prev->destroy_func) - prev->destroy_func (prev->data); - - g_mem_chunk_free (g_dataset_data_mem_chunk, prev); - } + g_datalist_clear_i (&datalist); } void @@ -117,91 +151,27 @@ g_dataset_destroy (gconstpointer dataset_location) g_return_if_fail (dataset_location != NULL); - dataset = g_dataset_lookup (dataset_location); - if (dataset) - g_dataset_destroy_i (dataset); -} - -void -g_dataset_id_set_destroy (gconstpointer dataset_location, - GQuark key_id, - GDestroyNotify destroy_func) -{ - g_return_if_fail (dataset_location != NULL); - - if (key_id) - { - register GDataset *dataset; - - dataset = g_dataset_lookup (dataset_location); - if (dataset) - { - register GDatasetData *list; - - list = dataset->data_list; - while (list) - { - if (list->id == key_id) - { - list->destroy_func = destroy_func; - return; - } - } - } - } -} - -gpointer -g_dataset_id_get_data (gconstpointer dataset_location, - GQuark key_id) -{ - g_return_val_if_fail (dataset_location != NULL, NULL); - - if (key_id) + if (g_dataset_location_ht) { - register GDataset *dataset; - dataset = g_dataset_lookup (dataset_location); if (dataset) - { - register GDatasetData *list; - - for (list = dataset->data_list; list; list = list->next) - if (list->id == key_id) - return list->data; - } + g_dataset_destroy_internal (dataset); } - - return NULL; } -void -g_dataset_id_set_data_full (gconstpointer dataset_location, - GQuark key_id, - gpointer data, - GDestroyNotify destroy_func) +static inline void +g_data_set_internal (gpointer *datalist, + GQuark key_id, + gpointer data, + GDestroyNotify destroy_func, + GDataset *d_dataset) { - register GDataset *dataset; - register GDatasetData *list; - - g_return_if_fail (dataset_location != NULL); - g_return_if_fail (key_id > 0); + register GData *list; - dataset = g_dataset_lookup (dataset_location); - if (!dataset) - { - dataset = g_chunk_new (GDataset, g_dataset_mem_chunk); - dataset->location = dataset_location; - dataset->data_list = NULL; - g_hash_table_insert (g_dataset_location_ht, - (gpointer) dataset->location, /* Yuck */ - dataset); - } - - list = dataset->data_list; + list = *datalist; if (!data) { - register GDatasetData *prev; + register GData *prev; prev = NULL; while (list) @@ -212,19 +182,30 @@ g_dataset_id_set_data_full (gconstpointer dataset_location, prev->next = list->next; else { - dataset->data_list = list->next; + *datalist = list->next; - if (!dataset->data_list) - g_dataset_destroy_i (dataset); + /* the dataset destruction *must* be done + * prior to invokation of the data destroy function + */ + if (!*datalist && d_dataset) + g_dataset_destroy_internal (d_dataset); } - /* we need to have unlinked before invoking the destroy function + /* the GData struct *must* already be unlinked + * when invoking the destroy function */ if (list->destroy_func) list->destroy_func (list->data); - g_mem_chunk_free (g_dataset_data_mem_chunk, list); - + if (g_data_cache_length < G_DATA_CACHE_MAX) + { + list->next = g_data_cache; + g_data_cache = list; + g_data_cache_length++; + } + else + g_mem_chunk_free (g_data_mem_chunk, list); + return; } @@ -238,37 +219,198 @@ g_dataset_id_set_data_full (gconstpointer dataset_location, { if (list->id == key_id) { - register GDestroyNotify dfunc; - register gpointer ddata; - - dfunc = list->destroy_func; - ddata = list->data; - list->data = data; - list->destroy_func = destroy_func; + if (!list->destroy_func) + { + list->data = data; + list->destroy_func = destroy_func; + } + else + { + register GDestroyNotify dfunc; + register gpointer ddata; + + dfunc = list->destroy_func; + ddata = list->data; + list->data = data; + list->destroy_func = destroy_func; + + /* we need to have updated all structures prior to + * invokation of the destroy function + */ + dfunc (ddata); + } - /* we need to have updated all structures prior to - * invokation of the destroy function - */ - if (dfunc) - dfunc (ddata); - return; } list = list->next; } - list = g_chunk_new (GDatasetData, g_dataset_data_mem_chunk); - list->next = dataset->data_list; + if (g_data_cache) + { + list = g_data_cache; + g_data_cache = list->next; + g_data_cache_length--; + } + else + list = g_chunk_new (GData, g_data_mem_chunk); + list->next = *datalist; list->id = key_id; list->data = data; list->destroy_func = destroy_func; - dataset->data_list = list; + *datalist = list; + } +} + +void +g_dataset_id_set_data_full (gconstpointer dataset_location, + GQuark key_id, + gpointer data, + GDestroyNotify destroy_func) +{ + register GDataset *dataset; + + g_return_if_fail (dataset_location != NULL); + if (!key_id) + { + if (data) + g_return_if_fail (key_id > 0); + else + return; + } + + if (!g_dataset_location_ht) + g_data_initialize (); + + dataset = g_dataset_lookup (dataset_location); + if (!dataset) + { + dataset = g_chunk_new (GDataset, g_dataset_mem_chunk); + dataset->location = dataset_location; + dataset->datalist = NULL; + g_hash_table_insert (g_dataset_location_ht, + (gpointer) dataset->location, + dataset); + } + + g_data_set_internal (&dataset->datalist, key_id, data, destroy_func, dataset); +} + +void +g_datalist_id_set_data_full (gpointer *datalist, + GQuark key_id, + gpointer data, + GDestroyNotify destroy_func) +{ + g_return_if_fail (datalist != NULL); + if (!key_id) + { + if (data) + g_return_if_fail (key_id > 0); + else + return; + } + + g_data_set_internal (datalist, key_id, data, destroy_func, NULL); +} + +void +g_dataset_id_set_destroy (gconstpointer dataset_location, + GQuark key_id, + GDestroyNotify destroy_func) +{ + register GDataset *dataset; + + g_return_if_fail (dataset_location != NULL); + g_return_if_fail (key_id > 0); + + if (g_dataset_location_ht) + { + dataset = g_dataset_lookup (dataset_location); + if (dataset) + { + register GData *list; + + for (list = dataset->datalist; list; list = list->next) + if (list->id == key_id) + { + list->destroy_func = destroy_func; + break; + } + } + } +} + +void +g_datalist_id_set_destroy (gpointer *datalist, + GQuark key_id, + GDestroyNotify destroy_func) +{ + register GData *list; + + g_return_if_fail (datalist != NULL); + g_return_if_fail (key_id > 0); + + for (list = *datalist; list; list = list->next) + if (list->id == key_id) + { + list->destroy_func = destroy_func; + break; + } +} + +gpointer +g_dataset_id_get_data (gconstpointer dataset_location, + GQuark key_id) +{ + g_return_val_if_fail (dataset_location != NULL, NULL); + + if (key_id && g_dataset_location_ht) + { + register GDataset *dataset; + + dataset = g_dataset_lookup (dataset_location); + if (dataset) + { + register GData *list; + + for (list = dataset->datalist; list; list = list->next) + if (list->id == key_id) + return list->data; + } } + + return NULL; +} + +gpointer +g_datalist_id_get_data (gpointer *datalist, + GQuark key_id) +{ + g_return_val_if_fail (datalist != NULL, NULL); + + if (key_id) + { + register GData *list; + + for (list = *datalist; list; list = list->next) + if (list->id == key_id) + return list->data; + } + + return NULL; +} + +void +g_datalist_init (gpointer *datalist) +{ + g_return_if_fail (datalist != NULL); + + *datalist = NULL; } static void -g_dataset_initialize (void) +g_data_initialize (void) { if (!g_dataset_location_ht) { @@ -280,10 +422,10 @@ g_dataset_initialize (void) sizeof (GDataset), sizeof (GDataset) * G_DATASET_MEM_CHUNK_PREALLOC, G_ALLOC_AND_FREE); - g_dataset_data_mem_chunk = - g_mem_chunk_new ("GDatasetData MemChunk", - sizeof (GDatasetData), - sizeof (GDatasetData) * G_DATASET_DATA_MEM_CHUNK_PREALLOC, + g_data_mem_chunk = + g_mem_chunk_new ("GData MemChunk", + sizeof (GData), + sizeof (GData) * G_DATA_MEM_CHUNK_PREALLOC, G_ALLOC_AND_FREE); } } @@ -307,7 +449,7 @@ g_quark_from_string (const gchar *string) g_return_val_if_fail (string != NULL, 0); if (!g_quark_ht) - g_dataset_initialize (); + g_data_initialize (); quark = (gulong) g_hash_table_lookup (g_quark_ht, string); if (!quark) @@ -324,7 +466,7 @@ g_quark_from_static_string (const gchar *string) g_return_val_if_fail (string != NULL, 0); if (!g_quark_ht) - g_dataset_initialize (); + g_data_initialize (); quark = (gulong) g_hash_table_lookup (g_quark_ht, string); if (!quark) @@ -347,9 +489,9 @@ g_quark_new (const gchar *string) { GQuark quark; - if (g_quark_seq_id % G_DATASET_BLOCK_SIZE == 0) + if (g_quark_seq_id % G_QUARK_BLOCK_SIZE == 0) g_quarks = g_realloc (g_quarks, - (g_quark_seq_id + G_DATASET_BLOCK_SIZE) * sizeof (gchar*)); + (g_quark_seq_id + G_QUARK_BLOCK_SIZE) * sizeof (gchar*)); g_quarks[g_quark_seq_id] = (gchar*) string; diff --git a/glib/glib.h b/glib/glib.h index f4d738b3..0512e8b6 100644 --- a/glib/glib.h +++ b/glib/glib.h @@ -1441,7 +1441,36 @@ GQuark g_quark_from_string (const gchar *string); gchar* g_quark_to_string (GQuark quark); -/* Location Associated Data +/* Keyed Data List + */ +void g_datalist_init (gpointer *datalist); +void g_datalist_clear (gpointer *datalist); +gpointer g_datalist_id_get_data (gpointer *datalist, + GQuark key_id); +void g_datalist_id_set_data_full (gpointer *datalist, + GQuark key_id, + gpointer data, + GDestroyNotify destroy_func); +void g_datalist_id_set_destroy (gpointer *datalist, + GQuark key_id, + GDestroyNotify destroy_func); +#define g_datalist_id_set_data(dl, q, d) \ + g_datalist_id_set_data_full ((dl), (q), (d), NULL) +#define g_datalist_id_remove_data(dl, q) \ + g_datalist_id_set_data ((dl), (q), NULL) +#define g_datalist_get_data(dl, k) \ + (g_datalist_id_get_data ((dl), g_quark_try_string ((k)))) +#define g_datalist_set_data_full(dl, k, d, f) \ + g_datalist_id_set_data_full ((dl), g_quark_from_string ((k)), (d), (f)) +#define g_datalist_set_destroy(dl, k, f) \ + g_datalist_id_set_destroy ((dl), g_quark_try_string ((k)), (f)) +#define g_datalist_set_data(dl, k, d) \ + g_datalist_set_data_full ((dl), (k), (d), NULL) +#define g_datalist_remove_data(dl, k) \ + g_datalist_id_set_data ((dl), g_quark_try_string ((k)), NULL) + + +/* Location Associated Keyed Data */ void g_dataset_destroy (gconstpointer dataset_location); gpointer g_dataset_id_get_data (gconstpointer dataset_location, @@ -1458,15 +1487,15 @@ void g_dataset_id_set_destroy (gconstpointer dataset_location, #define g_dataset_id_remove_data(l, k) \ g_dataset_id_set_data ((l), (k), NULL) #define g_dataset_get_data(l, k) \ - (g_dataset_id_get_data ((l), g_quark_try_string (k))) + (g_dataset_id_get_data ((l), g_quark_try_string ((k)))) #define g_dataset_set_data_full(l, k, d, f) \ - g_dataset_id_set_data_full ((l), g_quark_from_string (k), (d), (f)) + g_dataset_id_set_data_full ((l), g_quark_from_string ((k)), (d), (f)) #define g_dataset_set_destroy(l, k, f) \ - g_dataset_id_set_destroy ((l), g_quark_from_string (k), (f)) + g_dataset_id_set_destroy ((l), g_quark_try_string ((k)), (f)) #define g_dataset_set_data(l, k, d) \ g_dataset_set_data_full ((l), (k), (d), NULL) -#define g_dataset_remove_data(l,k) \ - g_dataset_set_data ((l), (k), NULL) +#define g_dataset_remove_data(l, k) \ + g_dataset_id_set_data ((l), g_quark_try_string ((k)), NULL) /* GScanner: Flexible lexical scanner for general purpose. diff --git a/gmodule/ChangeLog b/gmodule/ChangeLog index ba2cfaf7..723d5242 100644 --- a/gmodule/ChangeLog +++ b/gmodule/ChangeLog @@ -1,3 +1,11 @@ +Thu Sep 17 06:34:22 1998 Tim Janik + + * gmodule.h: + * gmodule.c: implemented g_module_make_resident() which can be + used to make modules resident. + fixed a buglet about the optional "g_module_de_init" function in + modules, which could get invoked twice on very obscure occasions. + Tue Sep 15 14:57:30 1998 Owen Taylor * Makefile.am: Update to libtool-1.2b, @@ -51,7 +59,7 @@ Sun Aug 9 15:57:38 1998 Tim Janik * gmodule.h: * gmodule.c: GModule library implementation, which is basically - a wrapper about system specifc dynamic loading functions. + a wrapper about system specifc dynamic loading facilities. Sun Aug 9 10:31:05 1998 Tim Janik diff --git a/gmodule/gmodule.c b/gmodule/gmodule.c index 6ab51086..04d435e2 100644 --- a/gmodule/gmodule.c +++ b/gmodule/gmodule.c @@ -36,7 +36,8 @@ struct _GModule { gchar *file_name; gpointer handle; - guint ref_count; + guint ref_count : 31; + guint is_resident : 1; GModuleDeInit de_init; GModule *next; }; @@ -164,6 +165,7 @@ g_module_open (const gchar *file_name, main_module->file_name = NULL; main_module->handle = handle; main_module->ref_count = 1; + main_module->is_resident = TRUE; main_module->de_init = NULL; main_module->next = NULL; } @@ -208,6 +210,7 @@ g_module_open (const gchar *file_name, module->file_name = g_strdup (file_name); module->handle = handle; module->ref_count = 1; + module->is_resident = FALSE; module->de_init = NULL; module->next = modules; modules = module; @@ -246,12 +249,18 @@ g_module_close (GModule *module) g_return_val_if_fail (module != NULL, FALSE); g_return_val_if_fail (module->ref_count > 0, FALSE); - if (module != main_module) - module->ref_count--; + module->ref_count--; - if (!module->ref_count && module->de_init) - module->de_init (module); - if (!module->ref_count) + if (!module->ref_count && !module->is_resident && module->de_init) + { + GModuleDeInit de_init; + + de_init = module->de_init; + module->de_init = NULL; + de_init (module); + } + + if (!module->ref_count && !module->is_resident) { GModule *last; GModule *node; @@ -282,6 +291,14 @@ g_module_close (GModule *module) return module_error == NULL; } +void +g_module_make_resident (GModule *module) +{ + g_return_if_fail (module != NULL); + + module->is_resident = TRUE; +} + gchar* g_module_error (void) { diff --git a/gmodule/gmodule.h b/gmodule/gmodule.h index 21788e3a..966d5ef4 100644 --- a/gmodule/gmodule.h +++ b/gmodule/gmodule.h @@ -56,6 +56,9 @@ GModule* g_module_open (const gchar *file_name, /* close a previously opened module, returns TRUE on success */ gboolean g_module_close (GModule *module); +/* make a module resident so g_module_close on it will be ignored */ +void g_module_make_resident (GModule *module); + /* query the last module error as a string */ gchar* g_module_error (void);