00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
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
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
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
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
00143 for (i = 0; i < pool->count; i++) {
00144 newpool->pool[i] = pool->pool[i];
00145 pool->pool[i] = NULL;
00146 }
00147
00148
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 }