[evolution-data-server] Add CamelMemChunk (copy of EMemChunk).



commit 5ce39d3904b8234a8aebe497fd82bc5b84d73cba
Author: Matthew Barnes <mbarnes redhat com>
Date:   Sat Sep 3 15:19:47 2011 -0400

    Add CamelMemChunk (copy of EMemChunk).
    
    To further erode Camel's dependence on libedataserver.

 camel/Makefile.am                             |    2 +
 camel/camel-certdb.c                          |    8 +-
 camel/camel-certdb.h                          |    3 +-
 camel/camel-folder-summary.h                  |    7 +-
 camel/camel-folder-thread.c                   |   34 +-
 camel/camel-folder-thread.h                   |    3 +-
 camel/camel-memchunk.c                        |  459 +++++++++++++++++++++++++
 camel/camel-memchunk.h                        |   49 +++
 camel/camel-store-summary.c                   |    4 +-
 camel/camel-store-summary.h                   |    3 +-
 camel/camel-trie.c                            |   19 +-
 camel/camel.h                                 |    1 +
 docs/reference/camel/camel-docs.sgml          |    5 +
 docs/reference/camel/camel-sections.txt       |   12 +
 docs/reference/camel/tmpl/camel-memchunk.sgml |   89 +++++
 15 files changed, 656 insertions(+), 42 deletions(-)
---
diff --git a/camel/Makefile.am b/camel/Makefile.am
index d58ac77..d74ab7f 100644
--- a/camel/Makefile.am
+++ b/camel/Makefile.am
@@ -196,6 +196,7 @@ libcamel_1_2_la_SOURCES = 			\
 	camel-list-utils.c			\
 	camel-lock.c				\
 	camel-medium.c				\
+	camel-memchunk.c			\
 	camel-mempool.c				\
 	camel-mime-filter-basic.c		\
 	camel-mime-filter-bestenc.c		\
@@ -267,6 +268,7 @@ libcamelinclude_HEADERS =			\
 	camel-lock-client.h			\
 	camel-lock.h				\
 	camel-medium.h				\
+	camel-memchunk.h			\
 	camel-mempool.h				\
 	camel-mime-filter-basic.h		\
 	camel-mime-filter-bestenc.h		\
diff --git a/camel/camel-certdb.c b/camel/camel-certdb.c
index 68089d4..9241a1c 100644
--- a/camel/camel-certdb.c
+++ b/camel/camel-certdb.c
@@ -34,8 +34,6 @@
 
 #include <glib/gstdio.h>
 
-#include <libedataserver/e-memory.h>
-
 #include "camel-certdb.h"
 #include "camel-file-utils.h"
 #include "camel-win32.h"
@@ -79,7 +77,7 @@ certdb_finalize (GObject *object)
 	g_free (certdb->filename);
 
 	if (certdb->cert_chunks)
-		e_memchunk_destroy (certdb->cert_chunks);
+		camel_memchunk_destroy (certdb->cert_chunks);
 
 	g_mutex_free (priv->db_lock);
 	g_mutex_free (priv->io_lock);
@@ -478,7 +476,7 @@ certdb_cert_new (CamelCertDB *certdb)
 	CamelCert *cert;
 
 	if (certdb->cert_chunks)
-		cert = e_memchunk_alloc0 (certdb->cert_chunks);
+		cert = camel_memchunk_alloc0 (certdb->cert_chunks);
 	else
 		cert = g_malloc0 (certdb->cert_size);
 
@@ -548,7 +546,7 @@ camel_certdb_cert_unref (CamelCertDB *certdb,
 	if (cert->refcount <= 1) {
 		class->cert_free (certdb, cert);
 		if (certdb->cert_chunks)
-			e_memchunk_free (certdb->cert_chunks, cert);
+			camel_memchunk_free (certdb->cert_chunks, cert);
 		else
 			g_free (cert);
 	} else {
diff --git a/camel/camel-certdb.h b/camel/camel-certdb.h
index 521a22f..c289e72 100644
--- a/camel/camel-certdb.h
+++ b/camel/camel-certdb.h
@@ -28,6 +28,7 @@
 #define CAMEL_CERTDB_H
 
 #include <stdio.h>
+#include <camel/camel-memchunk.h>
 #include <camel/camel-object.h>
 
 /* Standard GObject macros */
@@ -109,7 +110,7 @@ struct _CamelCertDB {
 
 	guint32 cert_size;
 
-	struct _EMemChunk *cert_chunks;
+	CamelMemChunk *cert_chunks;
 
 	GPtrArray *certs;
 	GHashTable *cert_hash;
diff --git a/camel/camel-folder-summary.h b/camel/camel-folder-summary.h
index 9423643..aaba7ae 100644
--- a/camel/camel-folder-summary.h
+++ b/camel/camel-folder-summary.h
@@ -29,9 +29,10 @@
 #include <stdio.h>
 #include <time.h>
 
+#include <camel/camel-index.h>
+#include <camel/camel-memchunk.h>
 #include <camel/camel-mime-message.h>
 #include <camel/camel-mime-parser.h>
-#include <camel/camel-index.h>
 
 /* Standard GObject macros */
 #define CAMEL_TYPE_FOLDER_SUMMARY \
@@ -249,8 +250,8 @@ struct _CamelFolderSummary {
 	guint32 visible_count;
 
 	/* memory allocators (setup automatically) */
-	struct _EMemChunk *message_info_chunks;
-	struct _EMemChunk *content_info_chunks;
+	CamelMemChunk *message_info_chunks;
+	CamelMemChunk *content_info_chunks;
 
 	gchar *summary_path;
 	gboolean build_content;	/* do we try and parse/index the content, or not? */
diff --git a/camel/camel-folder-thread.c b/camel/camel-folder-thread.c
index e00c623..0c3f9b9 100644
--- a/camel/camel-folder-thread.c
+++ b/camel/camel-folder-thread.c
@@ -33,8 +33,6 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
-#include <libedataserver/e-memory.h>
-
 #include "camel-folder-thread.h"
 
 #define d(x)
@@ -119,7 +117,7 @@ prune_empty (CamelFolderThread *thread,
 				d(printf("removing empty node\n"));
 				lastc->next = c->next;
 				m (memset (c, 0xfe, sizeof (*c)));
-				e_memchunk_free (thread->node_chunks, c);
+				camel_memchunk_free (thread->node_chunks, c);
 				continue;
 			}
 			if (c->parent || c->child->next == NULL) {
@@ -274,7 +272,7 @@ group_root_set (CamelFolderThread *thread,
 				scan->next = c->child;
 				clast->next = c->next;
 				m (memset (c, 0xee, sizeof (*c)));
-				e_memchunk_free (thread->node_chunks, c);
+				camel_memchunk_free (thread->node_chunks, c);
 				continue;
 			} if (c->message == NULL && container->message != NULL) {
 				d(printf("container is non-empty parent\n"));
@@ -301,7 +299,7 @@ group_root_set (CamelFolderThread *thread,
 				remove_node (cp, container, &clast);
 				remove_node (cp, c, &clast);
 
-				scan = e_memchunk_alloc0 (thread->node_chunks);
+				scan = camel_memchunk_alloc0 (thread->node_chunks);
 
 				scan->root_subject = c->root_subject;
 				scan->re = c->re && container->re;
@@ -471,16 +469,16 @@ thread_summary (CamelFolderThread *thread,
 				/* if duplicate, just make out it is a no-id message,  but try and insert it
 				 * into the right spot in the tree */
 				d(printf("doing: (duplicate message id)\n"));
-				c = e_memchunk_alloc0 (thread->node_chunks);
+				c = camel_memchunk_alloc0 (thread->node_chunks);
 				g_hash_table_insert (no_id_table, (gpointer) mi, c);
 			} else if (!c) {
 				d(printf("doing : %08x%08x (%s)\n", mid->id.part.hi, mid->id.part.lo, camel_message_info_subject(mi)));
-				c = e_memchunk_alloc0 (thread->node_chunks);
+				c = camel_memchunk_alloc0 (thread->node_chunks);
 				g_hash_table_insert (id_table, (gpointer) mid, c);
 			}
 		} else {
 			d(printf("doing : (no message id)\n"));
-			c = e_memchunk_alloc0 (thread->node_chunks);
+			c = camel_memchunk_alloc0 (thread->node_chunks);
 			g_hash_table_insert (no_id_table, (gpointer) mi, c);
 		}
 
@@ -501,7 +499,7 @@ thread_summary (CamelFolderThread *thread,
 				c = g_hash_table_lookup (id_table, &references->references[j]);
 				if (c == NULL) {
 					d(printf("%s (%s) not found\n", G_STRLOC, G_STRFUNC));
-					c = e_memchunk_alloc0 (thread->node_chunks);
+					c = camel_memchunk_alloc0 (thread->node_chunks);
 					g_hash_table_insert (id_table, (gpointer) &references->references[j], c);
 				} else
 					found = TRUE;
@@ -569,7 +567,7 @@ thread_summary (CamelFolderThread *thread,
 			newtop->next = child->next;
 			c = newtop;
 			m (memset (child, 0xde, sizeof (*child)));
-			e_memchunk_free (thread->node_chunks, child);
+			camel_memchunk_free (thread->node_chunks, child);
 		} else {
 			c = child;
 		}
@@ -629,7 +627,7 @@ camel_folder_thread_messages_new (CamelFolder *folder,
 	thread->refcount = 1;
 	thread->subject = thread_subject;
 	thread->tree = NULL;
-	thread->node_chunks = e_memchunk_new (32, sizeof (CamelFolderThreadNode));
+	thread->node_chunks = camel_memchunk_new (32, sizeof (CamelFolderThreadNode));
 	thread->folder = g_object_ref (folder);
 
 	camel_folder_summary_prepare_fetch_all (folder->summary, NULL);
@@ -704,8 +702,8 @@ camel_folder_thread_messages_apply (CamelFolderThread *thread,
 	g_hash_table_destroy (table);
 
 	thread->tree = NULL;
-	e_memchunk_destroy (thread->node_chunks);
-	thread->node_chunks = e_memchunk_new (32, sizeof (CamelFolderThreadNode));
+	camel_memchunk_destroy (thread->node_chunks);
+	thread->node_chunks = camel_memchunk_new (32, sizeof (CamelFolderThreadNode));
 	thread_summary (thread, all);
 
 	g_ptr_array_free (thread->summary, TRUE);
@@ -740,7 +738,7 @@ camel_folder_thread_messages_unref (CamelFolderThread *thread)
 		g_ptr_array_free (thread->summary, TRUE);
 		g_object_unref (thread->folder);
 	}
-	e_memchunk_destroy (thread->node_chunks);
+	camel_memchunk_destroy (thread->node_chunks);
 	g_free (thread);
 }
 
@@ -771,7 +769,7 @@ camel_folder_thread_messages_new_summary (GPtrArray *summary)
 	thread = g_malloc (sizeof (*thread));
 	thread->refcount = 1;
 	thread->tree = NULL;
-	thread->node_chunks = e_memchunk_new (32, sizeof (CamelFolderThreadNode));
+	thread->node_chunks = camel_memchunk_new (32, sizeof (CamelFolderThreadNode));
 	thread->folder = NULL;
 	thread->summary = NULL;
 
@@ -823,7 +821,7 @@ camel_folder_thread_messages_add (CamelFolderThread *thread,
 
 	/* reset the tree, and rebuild fully */
 	thread->tree = NULL;
-	e_memchunk_empty (thread->node_chunks);
+	camel_memchunk_empty (thread->node_chunks);
 	thread_summary (thread, all);
 }
 
@@ -863,7 +861,7 @@ remove_uid_node_rec (CamelFolderThread *thread,
 
 				rest = next->next;
 				node->next = child;
-				e_memchunk_free (thread->node_chunks, next);
+				camel_memchunk_free (thread->node_chunks, next);
 				next = child;
 				do {
 					lchild = child;
@@ -880,7 +878,7 @@ remove_uid_node_rec (CamelFolderThread *thread,
 				 * node
 				 * rest */
 				node->next = next->next;
-				e_memchunk_free (thread->node_chunks, next);
+				camel_memchunk_free (thread->node_chunks, next);
 				next = node->next;
 			}
 		} else {
diff --git a/camel/camel-folder-thread.h b/camel/camel-folder-thread.h
index 850c918..bd08039 100644
--- a/camel/camel-folder-thread.h
+++ b/camel/camel-folder-thread.h
@@ -28,6 +28,7 @@
 
 #include <camel/camel-folder-summary.h>
 #include <camel/camel-folder.h>
+#include <camel/camel-memchunk.h>
 
 G_BEGIN_DECLS
 
@@ -44,7 +45,7 @@ typedef struct _CamelFolderThread {
 	guint32 subject   : 1;
 
 	struct _CamelFolderThreadNode *tree;
-	struct _EMemChunk *node_chunks;
+	CamelMemChunk *node_chunks;
 	CamelFolder *folder;
 	GPtrArray *summary;
 } CamelFolderThread;
diff --git a/camel/camel-memchunk.c b/camel/camel-memchunk.c
new file mode 100644
index 0000000..ffa562a
--- /dev/null
+++ b/camel/camel-memchunk.c
@@ -0,0 +1,459 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ * Authors: Michael Zucchi <notzed ximian com>
+ *	    Jacob Berkman <jacob ximian com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ *
+*/
+
+#include "camel-memchunk.h"
+
+#include <string.h> /* memset() */
+
+/*#define TIMEIT*/
+
+#ifdef TIMEIT
+#include <sys/time.h>
+#include <unistd.h>
+
+struct timeval timeit_start;
+
+static void
+time_start (const gchar *desc)
+{
+	gettimeofday (&timeit_start, NULL);
+	printf("starting: %s\n", desc);
+}
+
+static void
+time_end (const gchar *desc)
+{
+	gulong diff;
+	struct timeval end;
+
+	gettimeofday (&end, NULL);
+	diff = end.tv_sec * 1000 + end.tv_usec / 1000;
+	diff -= timeit_start.tv_sec * 1000 + timeit_start.tv_usec / 1000;
+	printf("%s took %ld.%03ld seconds\n",
+	       desc, diff / 1000, diff % 1000);
+}
+#else
+#define time_start(x)
+#define time_end(x)
+#endif
+
+typedef struct _MemChunkFreeNode {
+	struct _MemChunkFreeNode *next;
+	guint atoms;
+} MemChunkFreeNode;
+
+/**
+ * CamelMemChunk:
+ *
+ * Since: 3.4
+ **/
+struct _CamelMemChunk {
+	guint blocksize;	/* number of atoms in a block */
+	guint atomsize;	/* size of each atom */
+	GPtrArray *blocks;	/* blocks of raw memory */
+	struct _MemChunkFreeNode *free;
+};
+
+/**
+ * camel_memchunk_new:
+ * @atomcount: the number of atoms stored in a single malloc'd block of memory
+ * @atomsize: the size of each allocation
+ *
+ * Create a new #CamelMemChunk header.  Memchunks are an efficient way to
+ * allocate and deallocate identical sized blocks of memory quickly, and
+ * space efficiently.
+ *
+ * camel_memchunks are effectively the same as gmemchunks, only faster (much),
+ * and they use less memory overhead for housekeeping.
+ *
+ * Returns: a new #CamelMemChunk
+ *
+ * Since: 3.4
+ **/
+CamelMemChunk *
+camel_memchunk_new (gint atomcount,
+                    gint atomsize)
+{
+	CamelMemChunk *memchunk = g_malloc (sizeof (*memchunk));
+
+	memchunk->blocksize = atomcount;
+	memchunk->atomsize = MAX (atomsize, sizeof (MemChunkFreeNode));
+	memchunk->blocks = g_ptr_array_new ();
+	memchunk->free = NULL;
+
+	return memchunk;
+}
+
+/**
+ * camel_memchunk_alloc:
+ * @memchunk: an #CamelMemChunk
+ *
+ * Allocate a new atom size block of memory from an #CamelMemChunk.
+ * Free the returned atom with camel_memchunk_free().
+ *
+ * Returns: an allocated block of memory
+ *
+ * Since: 3.4
+ **/
+gpointer
+camel_memchunk_alloc (CamelMemChunk *memchunk)
+{
+	gchar *b;
+	MemChunkFreeNode *f;
+	gpointer mem;
+
+	f = memchunk->free;
+	if (f) {
+		f->atoms--;
+		if (f->atoms > 0) {
+			mem = ((gchar *) f) + (f->atoms * memchunk->atomsize);
+		} else {
+			mem = f;
+			memchunk->free = memchunk->free->next;
+		}
+		return mem;
+	} else {
+		b = g_malloc (memchunk->blocksize * memchunk->atomsize);
+		g_ptr_array_add (memchunk->blocks, b);
+		f = (MemChunkFreeNode *) &b[memchunk->atomsize];
+		f->atoms = memchunk->blocksize - 1;
+		f->next = NULL;
+		memchunk->free = f;
+		return b;
+	}
+}
+
+/**
+ * camel_memchunk_alloc0:
+ * @memchunk: an #CamelMemChunk
+ *
+ * Allocate a new atom size block of memory from an #CamelMemChunk,
+ * and fill the memory with zeros.  Free the returned atom with
+ * camel_memchunk_free().
+ *
+ * Returns: an allocated block of memory
+ *
+ * Since: 3.4
+ **/
+gpointer
+camel_memchunk_alloc0 (CamelMemChunk *memchunk)
+{
+	gpointer mem;
+
+	mem = camel_memchunk_alloc (memchunk);
+	memset (mem, 0, memchunk->atomsize);
+
+	return mem;
+}
+
+/**
+ * camel_memchunk_free:
+ * @memchunk: an #CamelMemChunk
+ * @mem: address of atom to free
+ *
+ * Free a single atom back to the free pool of atoms in the given
+ * memchunk.
+ *
+ * Since: 3.4
+ **/
+void
+camel_memchunk_free (CamelMemChunk *memchunk,
+                     gpointer mem)
+{
+	MemChunkFreeNode *f;
+
+	/* Put the location back in the free list.  If we knew if the
+	 * preceeding or following cells were free, we could merge the
+	 * free nodes, but it doesn't really add much. */
+	f = mem;
+	f->next = memchunk->free;
+	memchunk->free = f;
+	f->atoms = 1;
+
+	/* We could store the free list sorted - we could then do the above,
+	 * and also probably improve the locality of reference properties for
+	 * the allocator.  (And it would simplify some other algorithms at
+	 * that, but slow this one down significantly.) */
+}
+
+/**
+ * camel_memchunk_empty:
+ * @memchunk: an #CamelMemChunk
+ *
+ * Clean out the memchunk buffers.  Marks all allocated memory as free blocks,
+ * but does not give it back to the system.  Can be used if the memchunk
+ * is to be used repeatedly.
+ *
+ * Since: 3.4
+ **/
+void
+camel_memchunk_empty (CamelMemChunk *memchunk)
+{
+	MemChunkFreeNode *f, *h = NULL;
+	gint i;
+
+	for (i = 0; i < memchunk->blocks->len; i++) {
+		f = (MemChunkFreeNode *) memchunk->blocks->pdata[i];
+		f->atoms = memchunk->blocksize;
+		f->next = h;
+		h = f;
+	}
+
+	memchunk->free = h;
+}
+
+struct _cleaninfo {
+	struct _cleaninfo *next;
+	gchar *base;
+	gint count;
+	gint size;		/* just so tree_search has it, sigh */
+};
+
+static gint
+tree_compare (struct _cleaninfo *a,
+              struct _cleaninfo *b)
+{
+	if (a->base < b->base)
+		return -1;
+	else if (a->base > b->base)
+		return 1;
+	return 0;
+}
+
+static gint
+tree_search (struct _cleaninfo *a,
+             gchar *mem)
+{
+	if (a->base <= mem) {
+		if (mem < &a->base[a->size])
+			return 0;
+		return 1;
+	}
+	return -1;
+}
+
+/**
+ * camel_memchunk_clean:
+ * @memchunk: an #CamelMemChunk
+ *
+ * Scan all empty blocks and check for blocks which can be free'd
+ * back to the system.
+ *
+ * This routine may take a while to run if there are many allocated
+ * memory blocks (if the total number of allocations is many times
+ * greater than atomcount).
+ *
+ * Since: 3.4
+ **/
+void
+camel_memchunk_clean (CamelMemChunk *memchunk)
+{
+	GTree *tree;
+	gint i;
+	MemChunkFreeNode *f;
+	struct _cleaninfo *ci, *hi = NULL;
+
+	f = memchunk->free;
+	if (memchunk->blocks->len == 0 || f == NULL)
+		return;
+
+	/* first, setup the tree/list so we can map free block addresses to block addresses */
+	tree = g_tree_new ((GCompareFunc) tree_compare);
+	for (i = 0; i < memchunk->blocks->len; i++) {
+		ci = alloca (sizeof (*ci));
+		ci->count = 0;
+		ci->base = memchunk->blocks->pdata[i];
+		ci->size = memchunk->blocksize * memchunk->atomsize;
+		g_tree_insert (tree, ci, ci);
+		ci->next = hi;
+		hi = ci;
+	}
+
+	/* now, scan all free nodes, and count them in their tree node */
+	while (f) {
+		ci = g_tree_search (tree, (GCompareFunc) tree_search, f);
+		if (ci) {
+			ci->count += f->atoms;
+		} else {
+			g_warning("error, can't find free node in memory block\n");
+		}
+		f = f->next;
+	}
+
+	/* if any nodes are all free, free & unlink them */
+	ci = hi;
+	while (ci) {
+		if (ci->count == memchunk->blocksize) {
+			MemChunkFreeNode *prev = NULL;
+
+			f = memchunk->free;
+			while (f) {
+				if (tree_search (ci, (gpointer) f) == 0) {
+					/* prune this node from our free-node list */
+					if (prev)
+						prev->next = f->next;
+					else
+						memchunk->free = f->next;
+				} else {
+					prev = f;
+				}
+
+				f = f->next;
+			}
+
+			g_ptr_array_remove_fast (memchunk->blocks, ci->base);
+			g_free (ci->base);
+		}
+		ci = ci->next;
+	}
+
+	g_tree_destroy (tree);
+}
+
+/**
+ * camel_memchunk_destroy:
+ * @memchunk: an #CamelMemChunk
+ *
+ * Free the memchunk header, and all associated memory.
+ *
+ * Since: 3.4
+ **/
+void
+camel_memchunk_destroy (CamelMemChunk *memchunk)
+{
+	gint i;
+
+	if (memchunk == NULL)
+		return;
+
+	for (i = 0; i < memchunk->blocks->len; i++)
+		g_free (memchunk->blocks->pdata[i]);
+
+	g_ptr_array_free (memchunk->blocks, TRUE);
+
+	g_free (memchunk);
+}
+
+#if 0
+
+#define CHUNK_SIZE (20)
+#define CHUNK_COUNT (32)
+
+#define s(x)
+
+main ()
+{
+	gint i;
+	MemChunk *mc;
+	gpointer mem, *last;
+	GMemChunk *gmc;
+	struct _EStrv *s;
+
+	s = strv_new (8);
+	s = strv_set(s, 1, "Testing 1");
+	s = strv_set(s, 2, "Testing 2");
+	s = strv_set(s, 3, "Testing 3");
+	s = strv_set(s, 4, "Testing 4");
+	s = strv_set(s, 5, "Testing 5");
+	s = strv_set(s, 6, "Testing 7");
+
+	for (i = 0; i < 8; i++) {
+		printf("s[%d] = %s\n", i, strv_get(s, i));
+	}
+
+	s (sleep (5));
+
+	printf("packing ...\n");
+	s = strv_pack (s);
+
+	for (i = 0; i < 8; i++) {
+		printf("s[%d] = %s\n", i, strv_get(s, i));
+	}
+
+	printf("setting ...\n");
+
+	s = strv_set_ref(s, 1, "Testing 1 x");
+
+	for (i = 0; i < 8; i++) {
+		printf("s[%d] = %s\n", i, strv_get(s, i));
+	}
+
+	printf("packing ...\n");
+	s = strv_pack (s);
+
+	for (i = 0; i < 8; i++) {
+		printf("s[%d] = %s\n", i, strv_get(s, i));
+	}
+
+	strv_free (s);
+
+#if 0
+	time_start("Using memchunks");
+	mc = memchunk_new (CHUNK_COUNT, CHUNK_SIZE);
+	for (i = 0; i < 1000000; i++) {
+		mem = memchunk_alloc (mc);
+		if ((i & 1) == 0)
+			memchunk_free (mc, mem);
+	}
+	s (sleep (10));
+	memchunk_destroy (mc);
+	time_end("allocating 1000000 memchunks, freeing 500k");
+
+	time_start("Using gmemchunks");
+	gmc = g_mem_chunk_new("memchunk", CHUNK_SIZE, CHUNK_SIZE*CHUNK_COUNT, G_ALLOC_AND_FREE);
+	for (i = 0; i < 1000000; i++) {
+		mem = g_mem_chunk_alloc (gmc);
+		if ((i & 1) == 0)
+			g_mem_chunk_free (gmc, mem);
+	}
+	s (sleep (10));
+	g_mem_chunk_destroy (gmc);
+	time_end("allocating 1000000 gmemchunks, freeing 500k");
+
+	time_start("Using memchunks");
+	mc = memchunk_new (CHUNK_COUNT, CHUNK_SIZE);
+	for (i = 0; i < 1000000; i++) {
+		mem = memchunk_alloc (mc);
+	}
+	s (sleep (10));
+	memchunk_destroy (mc);
+	time_end("allocating 1000000 memchunks");
+
+	time_start("Using gmemchunks");
+	gmc = g_mem_chunk_new("memchunk", CHUNK_SIZE, CHUNK_COUNT*CHUNK_SIZE, G_ALLOC_ONLY);
+	for (i = 0; i < 1000000; i++) {
+		mem = g_mem_chunk_alloc (gmc);
+	}
+	s (sleep (10));
+	g_mem_chunk_destroy (gmc);
+	time_end("allocating 1000000 gmemchunks");
+
+	time_start("Using malloc");
+	for (i = 0; i < 1000000; i++) {
+		malloc (CHUNK_SIZE);
+	}
+	time_end("allocating 1000000 malloc");
+#endif
+
+}
+
+#endif
diff --git a/camel/camel-memchunk.h b/camel/camel-memchunk.h
new file mode 100644
index 0000000..3963ff2
--- /dev/null
+++ b/camel/camel-memchunk.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ * Authors: Michael Zucchi <notzed ximian com>
+ *	    Jacob Berkman <jacob ximian com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#if !defined (__CAMEL_H_INSIDE__) && !defined (CAMEL_COMPILATION)
+#error "Only <camel/camel.h> can be included directly."
+#endif
+
+#ifndef CAMEL_MEMCHUNK_H
+#define CAMEL_MEMCHUNK_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+/* memchunks - allocate/free fixed-size blocks of memory */
+/* this is like gmemchunk, only faster and less overhead (only 4 bytes for every atomcount allocations) */
+typedef struct _CamelMemChunk CamelMemChunk;
+
+CamelMemChunk *	camel_memchunk_new		(gint atomcount,
+						 gint atomsize);
+gpointer	camel_memchunk_alloc		(CamelMemChunk *memchunk);
+gpointer	camel_memchunk_alloc0		(CamelMemChunk *memchunk);
+void		camel_memchunk_free		(CamelMemChunk *memchunk,
+						 gpointer mem);
+void		camel_memchunk_empty		(CamelMemChunk *memchunk);
+void		camel_memchunk_clean		(CamelMemChunk *memchunk);
+void		camel_memchunk_destroy		(CamelMemChunk *memchunk);
+
+G_END_DECLS
+
+#endif /* CAMEL_MEMCHUNK_H */
diff --git a/camel/camel-store-summary.c b/camel/camel-store-summary.c
index 3a1da2d..1c4678e 100644
--- a/camel/camel-store-summary.c
+++ b/camel/camel-store-summary.c
@@ -34,8 +34,6 @@
 
 #include <glib/gstdio.h>
 
-#include <libedataserver/e-memory.h>
-
 #include "camel-file-utils.h"
 #include "camel-store-summary.h"
 #include "camel-url.h"
@@ -71,7 +69,7 @@ store_summary_finalize (GObject *object)
 	g_free (summary->summary_path);
 
 	if (summary->store_info_chunks != NULL)
-		e_memchunk_destroy (summary->store_info_chunks);
+		camel_memchunk_destroy (summary->store_info_chunks);
 
 	g_mutex_free (summary->priv->summary_lock);
 	g_mutex_free (summary->priv->io_lock);
diff --git a/camel/camel-store-summary.h b/camel/camel-store-summary.h
index d0ddb20..01f686e 100644
--- a/camel/camel-store-summary.h
+++ b/camel/camel-store-summary.h
@@ -29,6 +29,7 @@
 #include <stdio.h>
 
 #include <camel/camel-enums.h>
+#include <camel/camel-memchunk.h>
 #include <camel/camel-mime-parser.h>
 #include <camel/camel-object.h>
 #include <camel/camel-url.h>
@@ -108,7 +109,7 @@ struct _CamelStoreSummary {
 	guint32 store_info_size;
 
 	/* memory allocators (setup automatically) */
-	struct _EMemChunk *store_info_chunks;
+	CamelMemChunk *store_info_chunks;
 
 	gchar *summary_path;
 
diff --git a/camel/camel-trie.c b/camel/camel-trie.c
index acac762..8bc60c3 100644
--- a/camel/camel-trie.c
+++ b/camel/camel-trie.c
@@ -25,8 +25,7 @@
 #include <stdio.h>
 #include <string.h>
 
-#include <libedataserver/e-memory.h>
-
+#include "camel-memchunk.h"
 #include "camel-trie.h"
 
 #define d(x)
@@ -57,8 +56,8 @@ struct _CamelTrie {
 	GPtrArray *fail_states;
 	gboolean icase;
 
-	EMemChunk *match_chunks;
-	EMemChunk *state_chunks;
+	CamelMemChunk *match_chunks;
+	CamelMemChunk *state_chunks;
 };
 
 static inline gunichar
@@ -130,8 +129,8 @@ camel_trie_new (gboolean icase)
 	trie->fail_states = g_ptr_array_sized_new (8);
 	trie->icase = icase;
 
-	trie->match_chunks = e_memchunk_new (8, sizeof (struct _trie_match));
-	trie->state_chunks = e_memchunk_new (8, sizeof (struct _trie_state));
+	trie->match_chunks = camel_memchunk_new (8, sizeof (struct _trie_match));
+	trie->state_chunks = camel_memchunk_new (8, sizeof (struct _trie_state));
 
 	return trie;
 }
@@ -148,8 +147,8 @@ void
 camel_trie_free (CamelTrie *trie)
 {
 	g_ptr_array_free (trie->fail_states, TRUE);
-	e_memchunk_destroy (trie->match_chunks);
-	e_memchunk_destroy (trie->state_chunks);
+	camel_memchunk_destroy (trie->match_chunks);
+	camel_memchunk_destroy (trie->state_chunks);
 	g_free (trie);
 }
 
@@ -173,12 +172,12 @@ trie_insert (CamelTrie *trie,
 {
 	struct _trie_match *m;
 
-	m = e_memchunk_alloc (trie->match_chunks);
+	m = camel_memchunk_alloc (trie->match_chunks);
 	m->next = q->match;
 	m->c = c;
 
 	q->match = m;
-	q = m->state = e_memchunk_alloc (trie->state_chunks);
+	q = m->state = camel_memchunk_alloc (trie->state_chunks);
 	q->match = NULL;
 	q->fail = &trie->root;
 	q->final = 0;
diff --git a/camel/camel.h b/camel/camel.h
index 44baa86..ab674c7 100644
--- a/camel/camel.h
+++ b/camel/camel.h
@@ -59,6 +59,7 @@
 #include <camel/camel-lock-client.h>
 #include <camel/camel-lock-helper.h>
 #include <camel/camel-medium.h>
+#include <camel/camel-memchunk.h>
 #include <camel/camel-mempool.h>
 #include <camel/camel-mime-filter.h>
 #include <camel/camel-mime-filter-basic.h>
diff --git a/docs/reference/camel/camel-docs.sgml b/docs/reference/camel/camel-docs.sgml
index 621f2d4..9fc32b7 100644
--- a/docs/reference/camel/camel-docs.sgml
+++ b/docs/reference/camel/camel-docs.sgml
@@ -182,6 +182,7 @@
       <xi:include href="xml/camel-list-utils.xml"/>
       <xi:include href="xml/camel-lock.xml"/>
       <xi:include href="xml/camel-lock-client.xml"/>
+      <xi:include href="xml/camel-memchunk.xml"/>
       <xi:include href="xml/camel-mempool.xml"/>
       <xi:include href="xml/camel-mime-utils.xml"/>
       <xi:include href="xml/camel-movemail.xml"/>
@@ -211,6 +212,10 @@
       <title>Index of deprecated symbols</title>
       <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
     </index>
+    <index id="api-index-3.4" role="3.4">
+      <title>Index of new symbols in 3.4</title>
+      <xi:include href="xml/api-index-3.4.xml"><xi:fallback /></xi:include>
+    </index>
     <index id="api-index-3.2" role="3.2">
       <title>Index of new symbols in 3.2</title>
       <xi:include href="xml/api-index-3.2.xml"><xi:fallback /></xi:include>
diff --git a/docs/reference/camel/camel-sections.txt b/docs/reference/camel/camel-sections.txt
index 0f07fc0..5de1021 100644
--- a/docs/reference/camel/camel-sections.txt
+++ b/docs/reference/camel/camel-sections.txt
@@ -2802,6 +2802,18 @@ camel_unlock_folder
 </SECTION>
 
 <SECTION>
+<FILE>camel-memchunk</FILE>
+CamelMemChunk
+camel_memchunk_new
+camel_memchunk_alloc
+camel_memchunk_alloc0
+camel_memchunk_free
+camel_memchunk_empty
+camel_memchunk_clean
+camel_memchunk_destroy
+</SECTION>
+
+<SECTION>
 <FILE>camel-mempool</FILE>
 CamelMemPool
 CamelMemPoolFlags
diff --git a/docs/reference/camel/tmpl/camel-memchunk.sgml b/docs/reference/camel/tmpl/camel-memchunk.sgml
new file mode 100644
index 0000000..1f26740
--- /dev/null
+++ b/docs/reference/camel/tmpl/camel-memchunk.sgml
@@ -0,0 +1,89 @@
+<!-- ##### SECTION Title ##### -->
+camel-memchunk
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### STRUCT CamelMemChunk ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION camel_memchunk_new ##### -->
+<para>
+
+</para>
+
+ atomcount: 
+ atomsize: 
+ Returns: 
+
+
+<!-- ##### FUNCTION camel_memchunk_alloc ##### -->
+<para>
+
+</para>
+
+ memchunk: 
+ Returns: 
+
+
+<!-- ##### FUNCTION camel_memchunk_alloc0 ##### -->
+<para>
+
+</para>
+
+ memchunk: 
+ Returns: 
+
+
+<!-- ##### FUNCTION camel_memchunk_free ##### -->
+<para>
+
+</para>
+
+ memchunk: 
+ mem: 
+
+
+<!-- ##### FUNCTION camel_memchunk_empty ##### -->
+<para>
+
+</para>
+
+ memchunk: 
+
+
+<!-- ##### FUNCTION camel_memchunk_clean ##### -->
+<para>
+
+</para>
+
+ memchunk: 
+
+
+<!-- ##### FUNCTION camel_memchunk_destroy ##### -->
+<para>
+
+</para>
+
+ memchunk: 
+
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]