1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
21 #include "camel-mempool.h"
25 typedef struct _MemPoolNode {
26 struct _MemPoolNode *next;
31 typedef struct _MemPoolThresholdNode {
32 struct _MemPoolThresholdNode *next;
33 } MemPoolThresholdNode;
35 #define ALIGNED_SIZEOF(t) ((sizeof (t) + G_MEM_ALIGN - 1) & -G_MEM_ALIGN)
37 struct _CamelMemPool {
41 struct _MemPoolNode *blocks;
42 struct _MemPoolThresholdNode *threshold_blocks;
47 * @blocksize: The base blocksize to use for all system alocations.
48 * @threshold: If the allocation exceeds the threshold, then it is
49 * allocated separately and stored in a separate list.
50 * @flags: Alignment options: CAMEL_MEMPOOL_ALIGN_STRUCT uses native
51 * struct alignment, CAMEL_MEMPOOL_ALIGN_WORD aligns to 16 bits (2 bytes),
52 * and CAMEL_MEMPOOL_ALIGN_BYTE aligns to the nearest byte. The default
53 * is to align to native structures.
55 * Create a new mempool header. Mempools can be used to efficiently
56 * allocate data which can then be freed as a whole.
58 * Mempools can also be used to efficiently allocate arbitrarily
59 * aligned data (such as strings) without incurring the space overhead
60 * of aligning each allocation (which is not required for strings).
62 * However, each allocation cannot be freed individually, only all
70 camel_mempool_new (gint blocksize,
72 CamelMemPoolFlags flags)
76 pool = g_slice_new0 (CamelMemPool);
77 if (threshold >= blocksize)
78 threshold = blocksize * 2 / 3;
79 pool->blocksize = blocksize;
80 pool->threshold = threshold;
82 pool->threshold_blocks = NULL;
84 switch (flags & CAMEL_MEMPOOL_ALIGN_MASK) {
85 case CAMEL_MEMPOOL_ALIGN_STRUCT:
87 pool->align = G_MEM_ALIGN - 1;
89 case CAMEL_MEMPOOL_ALIGN_WORD:
92 case CAMEL_MEMPOOL_ALIGN_BYTE:
99 * camel_mempool_alloc:
100 * @pool: a #CamelMemPool
103 * Allocate a new data block in the mempool. Size will
104 * be rounded up to the mempool's alignment restrictions
110 camel_mempool_alloc (CamelMemPool *pool,
113 size = (size + pool->align) & (~(pool->align));
114 if (size >= pool->threshold) {
115 MemPoolThresholdNode *n;
117 n = g_malloc (ALIGNED_SIZEOF (*n) + size);
118 n->next = pool->threshold_blocks;
119 pool->threshold_blocks = n;
120 return (gchar *) n + ALIGNED_SIZEOF (*n);
122 register MemPoolNode *n;
125 if (n && n->free >= size) {
127 return (gchar *) n + ALIGNED_SIZEOF (*n) + n->free;
130 /* maybe we could do some sort of the free blocks based on size, but
131 * it doubt its worth it at all */
133 n = g_malloc (ALIGNED_SIZEOF (*n) + pool->blocksize);
134 n->next = pool->blocks;
136 n->free = pool->blocksize - size;
137 return (gchar *) n + ALIGNED_SIZEOF (*n) + n->free;
142 * camel_mempool_strdup:
143 * @pool: a #CamelMemPool
149 camel_mempool_strdup (CamelMemPool *pool,
154 out = camel_mempool_alloc (pool, strlen (str) + 1);
161 * camel_mempool_flush:
162 * @pool: a #CamelMemPool
163 * @freeall: free all system allocated blocks as well
165 * Flush used memory and mark allocated blocks as free.
167 * If @freeall is %TRUE, then all allocated blocks are free'd
168 * as well. Otherwise only blocks above the threshold are
169 * actually freed, and the others are simply marked as empty.
174 camel_mempool_flush (CamelMemPool *pool,
177 MemPoolThresholdNode *tn, *tw;
178 MemPoolNode *pw, *pn;
180 tw = pool->threshold_blocks;
186 pool->threshold_blocks = NULL;
199 pw->free = pool->blocksize;
206 * camel_mempool_destroy:
207 * @pool: a #CamelMemPool
209 * Free all memory associated with a mempool.
214 camel_mempool_destroy (CamelMemPool *pool)
217 camel_mempool_flush (pool, 1);
218 g_slice_free (CamelMemPool, pool);