pool.c revision 254897
10SN/A/* 2553SN/A * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") 30SN/A * 40SN/A * Permission to use, copy, modify, and/or distribute this software for any 50SN/A * purpose with or without fee is hereby granted, provided that the above 60SN/A * copyright notice and this permission notice appear in all copies. 7553SN/A * 80SN/A * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9553SN/A * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 100SN/A * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 110SN/A * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 120SN/A * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 130SN/A * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 140SN/A * PERFORMANCE OF THIS SOFTWARE. 150SN/A */ 160SN/A 170SN/A/* $Id$ */ 180SN/A 190SN/A/*! \file */ 200SN/A 21553SN/A#include <config.h> 22553SN/A 23553SN/A#include <string.h> 240SN/A 250SN/A#include <isc/mem.h> 260SN/A#include <isc/random.h> 270SN/A#include <isc/pool.h> 280SN/A#include <isc/util.h> 290SN/A 300SN/A/*** 310SN/A *** Types. 320SN/A ***/ 330SN/A 340SN/Astruct isc_pool { 350SN/A isc_mem_t * mctx; 360SN/A unsigned int count; 370SN/A isc_pooldeallocator_t free; 380SN/A isc_poolinitializer_t init; 390SN/A void * initarg; 400SN/A void ** pool; 410SN/A}; 420SN/A 430SN/A/*** 440SN/A *** Functions. 450SN/A ***/ 460SN/A 470SN/Astatic isc_result_t 480SN/Aalloc_pool(isc_mem_t *mctx, unsigned int count, isc_pool_t **poolp) { 490SN/A isc_pool_t *pool; 500SN/A 510SN/A pool = isc_mem_get(mctx, sizeof(*pool)); 52 if (pool == NULL) 53 return (ISC_R_NOMEMORY); 54 pool->count = count; 55 pool->free = NULL; 56 pool->init = NULL; 57 pool->initarg = NULL; 58 pool->mctx = NULL; 59 isc_mem_attach(mctx, &pool->mctx); 60 pool->pool = isc_mem_get(mctx, count * sizeof(void *)); 61 if (pool->pool == NULL) { 62 isc_mem_put(mctx, pool, sizeof(*pool)); 63 return (ISC_R_NOMEMORY); 64 } 65 memset(pool->pool, 0, count * sizeof(void *)); 66 67 *poolp = pool; 68 return (ISC_R_SUCCESS); 69} 70 71isc_result_t 72isc_pool_create(isc_mem_t *mctx, unsigned int count, 73 isc_pooldeallocator_t free, 74 isc_poolinitializer_t init, void *initarg, 75 isc_pool_t **poolp) 76{ 77 isc_pool_t *pool = NULL; 78 isc_result_t result; 79 unsigned int i; 80 81 INSIST(count > 0); 82 83 /* Allocate the pool structure */ 84 result = alloc_pool(mctx, count, &pool); 85 if (result != ISC_R_SUCCESS) 86 return (result); 87 88 pool->free = free; 89 pool->init = init; 90 pool->initarg = initarg; 91 92 /* Populate the pool */ 93 for (i = 0; i < count; i++) { 94 result = init(&pool->pool[i], initarg); 95 if (result != ISC_R_SUCCESS) { 96 isc_pool_destroy(&pool); 97 return (result); 98 } 99 } 100 101 *poolp = pool; 102 return (ISC_R_SUCCESS); 103} 104 105void * 106isc_pool_get(isc_pool_t *pool) { 107 isc_uint32_t i; 108 isc_random_get(&i); 109 return (pool->pool[i % pool->count]); 110} 111 112int 113isc_pool_count(isc_pool_t *pool) { 114 REQUIRE(pool != NULL); 115 return (pool->count); 116} 117 118isc_result_t 119isc_pool_expand(isc_pool_t **sourcep, unsigned int count, 120 isc_pool_t **targetp) 121{ 122 isc_result_t result; 123 isc_pool_t *pool; 124 125 REQUIRE(sourcep != NULL && *sourcep != NULL); 126 REQUIRE(targetp != NULL && *targetp == NULL); 127 128 pool = *sourcep; 129 if (count > pool->count) { 130 isc_pool_t *newpool = NULL; 131 unsigned int i; 132 133 /* Allocate a new pool structure */ 134 result = alloc_pool(pool->mctx, count, &newpool); 135 if (result != ISC_R_SUCCESS) 136 return (result); 137 138 newpool->free = pool->free; 139 newpool->init = pool->init; 140 newpool->initarg = pool->initarg; 141 142 /* Copy over the objects from the old pool */ 143 for (i = 0; i < pool->count; i++) { 144 newpool->pool[i] = pool->pool[i]; 145 pool->pool[i] = NULL; 146 } 147 148 /* Populate the new entries */ 149 for (i = pool->count; i < count; i++) { 150 result = pool->init(&newpool->pool[i], pool->initarg); 151 if (result != ISC_R_SUCCESS) { 152 isc_pool_destroy(&pool); 153 return (result); 154 } 155 } 156 157 isc_pool_destroy(&pool); 158 pool = newpool; 159 } 160 161 *sourcep = NULL; 162 *targetp = pool; 163 return (ISC_R_SUCCESS); 164} 165 166void 167isc_pool_destroy(isc_pool_t **poolp) { 168 unsigned int i; 169 isc_pool_t *pool = *poolp; 170 for (i = 0; i < pool->count; i++) { 171 if (pool->free != NULL && pool->pool[i] != NULL) 172 pool->free(&pool->pool[i]); 173 } 174 isc_mem_put(pool->mctx, pool->pool, pool->count * sizeof(void *)); 175 isc_mem_putanddetach(&pool->mctx, pool, sizeof(*pool)); 176 *poolp = NULL; 177} 178