1 1.1 haad /* $NetBSD: pool.h,v 1.1.1.1 2008/12/22 00:18:35 haad Exp $ */ 2 1.1 haad 3 1.1 haad /* 4 1.1 haad * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. 5 1.1 haad * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. 6 1.1 haad * 7 1.1 haad * This file is part of the device-mapper userspace tools. 8 1.1 haad * 9 1.1 haad * This copyrighted material is made available to anyone wishing to use, 10 1.1 haad * modify, copy, or redistribute it subject to the terms and conditions 11 1.1 haad * of the GNU Lesser General Public License v.2.1. 12 1.1 haad * 13 1.1 haad * You should have received a copy of the GNU Lesser General Public License 14 1.1 haad * along with this program; if not, write to the Free Software Foundation, 15 1.1 haad * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 1.1 haad */ 17 1.1 haad 18 1.1 haad #ifndef _DM_POOL_H 19 1.1 haad #define _DM_POOL_H 20 1.1 haad 21 1.1 haad #include <string.h> 22 1.1 haad #include <stdlib.h> 23 1.1 haad 24 1.1 haad /* 25 1.1 haad * The pool allocator is useful when you are going to allocate 26 1.1 haad * lots of memory, use the memory for a bit, and then free the 27 1.1 haad * memory in one go. A surprising amount of code has this usage 28 1.1 haad * profile. 29 1.1 haad * 30 1.1 haad * You should think of the pool as an infinite, contiguous chunk 31 1.1 haad * of memory. The front of this chunk of memory contains 32 1.1 haad * allocated objects, the second half is free. pool_alloc grabs 33 1.1 haad * the next 'size' bytes from the free half, in effect moving it 34 1.1 haad * into the allocated half. This operation is very efficient. 35 1.1 haad * 36 1.1 haad * pool_free frees the allocated object *and* all objects 37 1.1 haad * allocated after it. It is important to note this semantic 38 1.1 haad * difference from malloc/free. This is also extremely 39 1.1 haad * efficient, since a single pool_free can dispose of a large 40 1.1 haad * complex object. 41 1.1 haad * 42 1.1 haad * pool_destroy frees all allocated memory. 43 1.1 haad * 44 1.1 haad * eg, If you are building a binary tree in your program, and 45 1.1 haad * know that you are only ever going to insert into your tree, 46 1.1 haad * and not delete (eg, maintaining a symbol table for a 47 1.1 haad * compiler). You can create yourself a pool, allocate the nodes 48 1.1 haad * from it, and when the tree becomes redundant call pool_destroy 49 1.1 haad * (no nasty iterating through the tree to free nodes). 50 1.1 haad * 51 1.1 haad * eg, On the other hand if you wanted to repeatedly insert and 52 1.1 haad * remove objects into the tree, you would be better off 53 1.1 haad * allocating the nodes from a free list; you cannot free a 54 1.1 haad * single arbitrary node with pool. 55 1.1 haad */ 56 1.1 haad 57 1.1 haad struct pool; 58 1.1 haad 59 1.1 haad /* constructor and destructor */ 60 1.1 haad struct pool *pool_create(const char *name, size_t chunk_hint); 61 1.1 haad void pool_destroy(struct pool *p); 62 1.1 haad 63 1.1 haad /* simple allocation/free routines */ 64 1.1 haad void *pool_alloc(struct pool *p, size_t s); 65 1.1 haad void *pool_alloc_aligned(struct pool *p, size_t s, unsigned alignment); 66 1.1 haad void pool_empty(struct pool *p); 67 1.1 haad void pool_free(struct pool *p, void *ptr); 68 1.1 haad 69 1.1 haad /* 70 1.1 haad * Object building routines: 71 1.1 haad * 72 1.1 haad * These allow you to 'grow' an object, useful for 73 1.1 haad * building strings, or filling in dynamic 74 1.1 haad * arrays. 75 1.1 haad * 76 1.1 haad * It's probably best explained with an example: 77 1.1 haad * 78 1.1 haad * char *build_string(struct pool *mem) 79 1.1 haad * { 80 1.1 haad * int i; 81 1.1 haad * char buffer[16]; 82 1.1 haad * 83 1.1 haad * if (!pool_begin_object(mem, 128)) 84 1.1 haad * return NULL; 85 1.1 haad * 86 1.1 haad * for (i = 0; i < 50; i++) { 87 1.1 haad * snprintf(buffer, sizeof(buffer), "%d, ", i); 88 1.1 haad * if (!pool_grow_object(mem, buffer, strlen(buffer))) 89 1.1 haad * goto bad; 90 1.1 haad * } 91 1.1 haad * 92 1.1 haad * // add null 93 1.1 haad * if (!pool_grow_object(mem, "\0", 1)) 94 1.1 haad * goto bad; 95 1.1 haad * 96 1.1 haad * return pool_end_object(mem); 97 1.1 haad * 98 1.1 haad * bad: 99 1.1 haad * 100 1.1 haad * pool_abandon_object(mem); 101 1.1 haad * return NULL; 102 1.1 haad *} 103 1.1 haad * 104 1.1 haad * So start an object by calling pool_begin_object 105 1.1 haad * with a guess at the final object size - if in 106 1.1 haad * doubt make the guess too small. 107 1.1 haad * 108 1.1 haad * Then append chunks of data to your object with 109 1.1 haad * pool_grow_object. Finally get your object with 110 1.1 haad * a call to pool_end_object. 111 1.1 haad * 112 1.1 haad */ 113 1.1 haad int pool_begin_object(struct pool *p, size_t hint); 114 1.1 haad int pool_grow_object(struct pool *p, const void *extra, size_t delta); 115 1.1 haad void *pool_end_object(struct pool *p); 116 1.1 haad void pool_abandon_object(struct pool *p); 117 1.1 haad 118 1.1 haad /* utilities */ 119 1.1 haad char *pool_strdup(struct pool *p, const char *str); 120 1.1 haad char *pool_strndup(struct pool *p, const char *str, size_t n); 121 1.1 haad void *pool_zalloc(struct pool *p, size_t s); 122 1.1 haad 123 1.1 haad #endif 124