--- a/libpurple/memorypool.c Tue Mar 25 14:32:40 2014 +0100
+++ b/libpurple/memorypool.c Tue Mar 25 15:41:57 2014 +0100
@@ -137,6 +137,23 @@
+purple_memory_pool_cleanup_impl(PurpleMemoryPool *pool) + PurpleMemoryPoolPrivate *priv = PURPLE_MEMORY_POOL_GET_PRIVATE(pool); + PurpleMemoryPoolBlock *blk; + g_return_if_fail(priv != NULL); + blk = priv->first_block; + PurpleMemoryPoolBlock *next = blk->next; /*******************************************************************************
******************************************************************************/
@@ -191,6 +208,19 @@
+purple_memory_pool_cleanup(PurpleMemoryPool *pool) + PurpleMemoryPoolClass *klass; + g_return_if_fail(PURPLE_IS_MEMORY_POOL(pool)); + klass = PURPLE_MEMORY_POOL_GET_CLASS(pool); + g_return_if_fail(klass != NULL); /*******************************************************************************
@@ -212,18 +242,18 @@
return g_object_new(PURPLE_TYPE_MEMORY_POOL, NULL);
+purple_memory_pool_new_sized(gulong block_size) + return g_object_new(PURPLE_TYPE_MEMORY_POOL, + "block-size", block_size, purple_memory_pool_finalize(GObject *obj)
- PurpleMemoryPoolPrivate *priv = PURPLE_MEMORY_POOL_GET_PRIVATE(obj);
- PurpleMemoryPoolBlock *blk;
- blk = priv->first_block;
- PurpleMemoryPoolBlock *next = blk->next;
+ purple_memory_pool_cleanup(PURPLE_MEMORY_POOL(obj)); G_OBJECT_CLASS(parent_class)->finalize(obj);
@@ -274,6 +304,7 @@
obj_class->set_property = purple_memory_pool_set_property;
klass->palloc = purple_memory_pool_alloc_impl;
+ klass->cleanup = purple_memory_pool_cleanup_impl; properties[PROP_BLOCK_SIZE] = g_param_spec_ulong("block-size",
"Block size", "The default size of each block of pool memory.",
--- a/libpurple/memorypool.h Tue Mar 25 14:32:40 2014 +0100
+++ b/libpurple/memorypool.h Tue Mar 25 15:41:57 2014 +0100
@@ -53,6 +53,7 @@
gpointer (*palloc)(PurpleMemoryPool *pool, gsize size, guint alignment);
gpointer (*pfree)(PurpleMemoryPool *pool, gpointer mem);
+ void (*cleanup)(PurpleMemoryPool *pool); void (*purple_reserved1)(void);
void (*purple_reserved2)(void);
@@ -76,6 +77,16 @@
purple_memory_pool_new(void);
+ * purple_memory_pool_new_sized: + * Creates a new memory pool with non-default block size. + * Returns: The new #PurpleMemoryPool. +purple_memory_pool_new_sized(gulong block_size); * purple_memory_pool_alloc:
* @pool: The memory pool.
* @size: The size of memory to be allocated.
@@ -116,6 +127,16 @@
purple_memory_pool_free(PurpleMemoryPool *pool, gpointer mem);
+ * purple_memory_pool_cleanup: + * @pool: The memory pool. + * Marks all memory allocated within a memory pool as not used. It may free + * resources, but don't have to. +purple_memory_pool_cleanup(PurpleMemoryPool *pool); * purple_memory_pool_strdup:
* @pool: The memory pool.
* @str: The string to duplicate.
--- a/libpurple/trie.c Tue Mar 25 14:32:40 2014 +0100
+++ b/libpurple/trie.c Tue Mar 25 15:41:57 2014 +0100
@@ -27,14 +27,22 @@
#define PURPLE_TRIE_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_TRIE, PurpleTriePrivate))
+#define PURPLE_TRIE_STATES_POOL_BLOCK_SIZE 102400 typedef struct _PurpleTrieRecord PurpleTrieRecord;
+typedef struct _PurpleTrieState PurpleTrieState; +typedef struct _PurpleTrieRecordList PurpleTrieRecordList; - PurpleMemoryPool *records_mempool;
+ PurpleMemoryPool *records_str_mempool; + PurpleMemoryPool *records_obj_mempool; + PurpleTrieRecordList *records; + PurpleMemoryPool *states_mempool; + PurpleTrieState *root_state; @@ -43,6 +51,115 @@
+struct _PurpleTrieRecordList + PurpleTrieRecordList *next; + PurpleTrieRecordList *prev; + PurpleTrieState *parent; + PurpleTrieState **children; + PurpleTrieState *longest_suffix; + PurpleTrieRecord *found_word; +/******************************************************************************* + ******************************************************************************/ +static PurpleTrieRecordList * +purple_record_list_prepend(PurpleMemoryPool *mpool, + PurpleTrieRecordList *old_head, PurpleTrieRecord *rec) + PurpleTrieRecordList *new_head; + new_head = purple_memory_pool_alloc(mpool, + sizeof(PurpleTrieRecordList), sizeof(gpointer)); + new_head->next = old_head; + old_head->prev = new_head; +/******************************************************************************* + ******************************************************************************/ +purple_trie_states_cleanup(PurpleTrie *trie) + PurpleTriePrivate *priv = PURPLE_TRIE_GET_PRIVATE(trie); + g_return_if_fail(priv != NULL); + if (priv->root_state != NULL) { + purple_memory_pool_cleanup(priv->states_mempool); + priv->root_state = NULL; +/* Allocates a state and binds it to the parent. */ +static PurpleTrieState * +purple_trie_state_new(PurpleTrie *trie, PurpleTrieState *parent, guchar letter) + PurpleTriePrivate *priv = PURPLE_TRIE_GET_PRIVATE(trie); + PurpleTrieState *state; + g_return_val_if_fail(priv != NULL, NULL); + state = purple_memory_pool_alloc0(priv->states_mempool, + sizeof(PurpleTrieState), sizeof(gpointer)); + g_return_val_if_fail(state != NULL, NULL); + state->parent = parent; + if (parent->children == NULL) { + parent->children = purple_memory_pool_alloc0( + /* PurpleTrieState *children[sizeof(guchar)] */ + sizeof(guchar) * sizeof(gpointer), + if (parent->children == NULL) { + purple_memory_pool_free(priv->states_mempool, state); + parent->children[letter] = state; +purple_trie_states_build(PurpleTrie *trie) + PurpleTriePrivate *priv = PURPLE_TRIE_GET_PRIVATE(trie); + g_return_val_if_fail(priv != NULL, FALSE); + if (priv->root_state != NULL) + priv->root_state = root = purple_trie_state_new(trie, NULL, '\0'); + g_return_val_if_fail(root != NULL, FALSE); /*******************************************************************************
******************************************************************************/
@@ -56,11 +173,21 @@
g_return_if_fail(priv != NULL);
g_return_if_fail(word != NULL);
- rec = g_new(PurpleTrieRecord, 1);
- rec->word = purple_memory_pool_strdup(priv->records_mempool, word);
+ /* Every change in a trie invalidates longest_suffix map. + * These prefixes could be updated instead of cleaning the whole graph. + purple_trie_states_cleanup(trie); + rec = purple_memory_pool_alloc(priv->records_obj_mempool, + sizeof(PurpleTrieRecord), sizeof(gpointer)); + rec->word = purple_memory_pool_strdup(priv->records_str_mempool, word); - priv->records = g_slist_prepend(priv->records, rec);
+ priv->records = purple_record_list_prepend(priv->records_obj_mempool, + /* XXX: it won't be called here (it's inefficient), but in search function */ + purple_trie_states_build(trie); /*******************************************************************************
@@ -113,7 +240,10 @@
PurpleTrie *trie = PURPLE_TRIE(instance);
PurpleTriePrivate *priv = PURPLE_TRIE_GET_PRIVATE(trie);
- priv->records_mempool = purple_memory_pool_new();
+ priv->records_obj_mempool = purple_memory_pool_new(); + priv->records_str_mempool = purple_memory_pool_new(); + priv->states_mempool = purple_memory_pool_new_sized( + PURPLE_TRIE_STATES_POOL_BLOCK_SIZE); @@ -121,8 +251,9 @@
PurpleTriePrivate *priv = PURPLE_TRIE_GET_PRIVATE(obj);
- g_slist_free_full(priv->records, g_free);
- g_object_unref(priv->records_mempool);
+ g_object_unref(priv->records_obj_mempool); + g_object_unref(priv->records_str_mempool); + g_object_unref(priv->states_mempool); G_OBJECT_CLASS(parent_class)->finalize(obj);