pool.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2013, 2015  Internet Systems Consortium, Inc. ("ISC")
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00009  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00010  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00011  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00012  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00013  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00014  * PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 /* $Id$ */
00018 
00019 /*! \file */
00020 
00021 #include <config.h>
00022 
00023 #include <string.h>
00024 
00025 #include <isc/mem.h>
00026 #include <isc/random.h>
00027 #include <isc/pool.h>
00028 #include <isc/util.h>
00029 
00030 /***
00031  *** Types.
00032  ***/
00033 
00034 struct isc_pool {
00035         isc_mem_t *                     mctx;
00036         unsigned int                    count;
00037         isc_pooldeallocator_t           free;
00038         isc_poolinitializer_t           init;
00039         void *                          initarg;
00040         void **                         pool;
00041 };
00042 
00043 /***
00044  *** Functions.
00045  ***/
00046 
00047 static isc_result_t
00048 alloc_pool(isc_mem_t *mctx, unsigned int count, isc_pool_t **poolp) {
00049         isc_pool_t *pool;
00050 
00051         pool = isc_mem_get(mctx, sizeof(*pool));
00052         if (pool == NULL)
00053                 return (ISC_R_NOMEMORY);
00054         pool->count = count;
00055         pool->free = NULL;
00056         pool->init = NULL;
00057         pool->initarg = NULL;
00058         pool->mctx = NULL;
00059         isc_mem_attach(mctx, &pool->mctx);
00060         pool->pool = isc_mem_get(mctx, count * sizeof(void *));
00061         if (pool->pool == NULL) {
00062                 isc_mem_put(mctx, pool, sizeof(*pool));
00063                 return (ISC_R_NOMEMORY);
00064         }
00065         memset(pool->pool, 0, count * sizeof(void *));
00066 
00067         *poolp = pool;
00068         return (ISC_R_SUCCESS);
00069 }
00070 
00071 isc_result_t
00072 isc_pool_create(isc_mem_t *mctx, unsigned int count,
00073                    isc_pooldeallocator_t release,
00074                    isc_poolinitializer_t init, void *initarg,
00075                    isc_pool_t **poolp)
00076 {
00077         isc_pool_t *pool = NULL;
00078         isc_result_t result;
00079         unsigned int i;
00080 
00081         INSIST(count > 0);
00082 
00083         /* Allocate the pool structure */
00084         result = alloc_pool(mctx, count, &pool);
00085         if (result != ISC_R_SUCCESS)
00086                 return (result);
00087 
00088         pool->free = release;
00089         pool->init = init;
00090         pool->initarg = initarg;
00091 
00092         /* Populate the pool */
00093         for (i = 0; i < count; i++) {
00094                 result = init(&pool->pool[i], initarg);
00095                 if (result != ISC_R_SUCCESS) {
00096                         isc_pool_destroy(&pool);
00097                         return (result);
00098                 }
00099         }
00100 
00101         *poolp = pool;
00102         return (ISC_R_SUCCESS);
00103 }
00104 
00105 void *
00106 isc_pool_get(isc_pool_t *pool) {
00107         isc_uint32_t i;
00108         isc_random_get(&i);
00109         return (pool->pool[i % pool->count]);
00110 }
00111 
00112 int
00113 isc_pool_count(isc_pool_t *pool) {
00114         REQUIRE(pool != NULL);
00115         return (pool->count);
00116 }
00117 
00118 isc_result_t
00119 isc_pool_expand(isc_pool_t **sourcep, unsigned int count,
00120                    isc_pool_t **targetp)
00121 {
00122         isc_result_t result;
00123         isc_pool_t *pool;
00124 
00125         REQUIRE(sourcep != NULL && *sourcep != NULL);
00126         REQUIRE(targetp != NULL && *targetp == NULL);
00127 
00128         pool = *sourcep;
00129         if (count > pool->count) {
00130                 isc_pool_t *newpool = NULL;
00131                 unsigned int i;
00132 
00133                 /* Allocate a new pool structure */
00134                 result = alloc_pool(pool->mctx, count, &newpool);
00135                 if (result != ISC_R_SUCCESS)
00136                         return (result);
00137 
00138                 newpool->free = pool->free;
00139                 newpool->init = pool->init;
00140                 newpool->initarg = pool->initarg;
00141 
00142                 /* Copy over the objects from the old pool */
00143                 for (i = 0; i < pool->count; i++) {
00144                         newpool->pool[i] = pool->pool[i];
00145                         pool->pool[i] = NULL;
00146                 }
00147 
00148                 /* Populate the new entries */
00149                 for (i = pool->count; i < count; i++) {
00150                         result = pool->init(&newpool->pool[i], pool->initarg);
00151                         if (result != ISC_R_SUCCESS) {
00152                                 isc_pool_destroy(&pool);
00153                                 return (result);
00154                         }
00155                 }
00156 
00157                 isc_pool_destroy(&pool);
00158                 pool = newpool;
00159         }
00160 
00161         *sourcep = NULL;
00162         *targetp = pool;
00163         return (ISC_R_SUCCESS);
00164 }
00165 
00166 void
00167 isc_pool_destroy(isc_pool_t **poolp) {
00168         unsigned int i;
00169         isc_pool_t *pool = *poolp;
00170         for (i = 0; i < pool->count; i++) {
00171                 if (pool->free != NULL && pool->pool[i] != NULL)
00172                         pool->free(&pool->pool[i]);
00173         }
00174         isc_mem_put(pool->mctx, pool->pool, pool->count * sizeof(void *));
00175         isc_mem_putanddetach(&pool->mctx, pool, sizeof(*pool));
00176         *poolp = NULL;
00177 }

Generated on Tue Apr 28 17:41:05 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha