src/misc/pool.c

Go to the documentation of this file.
00001 
00008 #include <sys/types.h>
00009 #include <sys/stat.h>
00010 #include <pthread.h>
00011 #include <unistd.h>
00012 #include <stddef.h>
00013 #include <misc/result.h>
00014 #include <misc/malloc.h>
00015 #include <misc/pool.h>
00016 #include <misc/debug.h>
00017 #include <misc/mutex.h>
00018 #include <core/config.h>
00019 
00020 struct txc_pool_object_s {
00021         void   *buf;
00022         char   status;
00023         struct txc_pool_object_s *next;
00024         struct txc_pool_object_s *prev;
00025 };
00026 
00027 struct txc_pool_s {
00028         txc_mutex_t                   mutex;
00029         void                          *full_buf;                        
00030         txc_pool_object_t             *obj_list;
00031         txc_pool_object_t             *obj_free_head;
00032         txc_pool_object_t             *obj_allocated_head;
00033         unsigned int                  obj_free_num;
00034         unsigned int                  obj_allocated_num;
00035         unsigned int                  obj_size;
00036         unsigned int                  obj_num;
00037         txc_pool_object_constructor_t obj_constructor;
00038 };
00039 
00040 
00041 txc_result_t
00042 txc_pool_create(txc_pool_t **poolp, 
00043                 unsigned int obj_size, 
00044                 unsigned int obj_num, 
00045                 txc_pool_object_constructor_t obj_constructor) 
00046 {
00047         txc_pool_object_t *object_list;
00048         char *buf; 
00049         int i;
00050 
00051         *poolp = (txc_pool_t *) MALLOC(sizeof(txc_pool_t));
00052         if (*poolp == NULL) {
00053                 return TXC_R_NOMEMORY;
00054         }
00055         (*poolp)->obj_size = obj_size;
00056         (*poolp)->obj_num = obj_num;
00057         object_list = (txc_pool_object_t *) CALLOC(obj_num, 
00058                                                    sizeof(txc_pool_object_t));
00059         if (object_list == NULL) {
00060                 FREE(*poolp);
00061                 return TXC_R_NOMEMORY;
00062         }
00063         (*poolp)->obj_list = object_list;
00064         if ((buf = CALLOC(obj_num, obj_size)) == NULL) {  
00065                 FREE(object_list);
00066                 FREE(*poolp);
00067                 return TXC_R_NOMEMORY;
00068         }
00069         (*poolp)->full_buf = buf; 
00070         for (i=0;i<obj_num;i++) {
00071                 object_list[i].buf = &buf[i*obj_size];
00072                 object_list[i].next = &object_list[(i+1)%obj_num];
00073                 object_list[i].prev = &object_list[(i-1)%obj_num];
00074                 object_list[i].status = TXC_POOL_OBJECT_FREE;
00075                 if (obj_constructor != NULL) {
00076                         obj_constructor(object_list[i].buf);
00077                 }
00078         }
00079         object_list[0].prev = object_list[obj_num-1].next = NULL;
00080         (*poolp)->obj_free_num = obj_num;
00081         (*poolp)->obj_free_head = &object_list[0];      
00082         (*poolp)->obj_allocated_num = 0;
00083         (*poolp)->obj_allocated_head = NULL;    
00084         if (TXC_MUTEX_INIT(&((*poolp)->mutex), NULL) !=0) {
00085                 FREE(buf);
00086                 FREE(object_list);      
00087                 FREE(*poolp);
00088                 return TXC_R_NOTINITLOCK;
00089         }
00090         return TXC_R_SUCCESS;
00091 }
00092 
00093 
00094 txc_result_t 
00095 txc_pool_destroy(txc_pool_t **poolp) 
00096 {
00097         TXC_ASSERT(*poolp != NULL);
00098         FREE((*poolp)->full_buf);
00099         FREE((*poolp)->obj_list);       
00100         FREE(*poolp);
00101         *poolp = NULL;
00102         return TXC_R_SUCCESS;
00103 }
00104 
00105 
00106 txc_result_t
00107 txc_pool_object_alloc(txc_pool_t *pool, void **objp, int lock) 
00108 {
00109         txc_result_t result;
00110         txc_pool_object_t *pool_object;
00111 
00112         if (lock) { 
00113                 TXC_MUTEX_LOCK(&pool->mutex);
00114         }       
00115         if (pool->obj_free_num == 0) {
00116                 *objp = NULL;
00117                 result = TXC_R_NOMEMORY;
00118                 goto unlock;
00119         }
00120         pool_object = pool->obj_free_head;
00121         pool->obj_free_head = pool_object->next;
00122         if (pool->obj_free_head) {
00123                 pool->obj_free_head->prev = NULL;
00124         }
00125         pool_object->prev = NULL;
00126         pool_object->next = pool->obj_allocated_head;
00127         if (pool->obj_allocated_head) {
00128                 pool->obj_allocated_head->prev = pool_object;
00129         }
00130         pool->obj_allocated_head = pool_object; 
00131         pool->obj_allocated_num++;
00132         pool->obj_free_num--;
00133         *objp = pool_object->buf;
00134         pool_object->status = TXC_POOL_OBJECT_ALLOCATED;
00135         result = TXC_R_SUCCESS;
00136 unlock:
00137         if (lock) {
00138                 TXC_MUTEX_UNLOCK(&pool->mutex);
00139         }       
00140         return result;
00141 }
00142 
00143 
00144 void
00145 txc_pool_object_free(txc_pool_t *pool, void **objp, int lock) 
00146 {
00147         txc_pool_object_t *pool_object;
00148         unsigned int index;
00149 
00150         TXC_ASSERT(pool);
00151         TXC_ASSERT(*objp);
00152         if (lock) {
00153                 TXC_MUTEX_LOCK(&(pool->mutex));
00154         }       
00155         index = ((unsigned int) ( (char*) *objp - (char*) pool->full_buf)) / pool->obj_size;
00156         pool_object = &pool->obj_list[index];
00157         TXC_ASSERT(pool_object->status == TXC_POOL_OBJECT_ALLOCATED);
00158         if (pool_object->prev) {
00159                 pool_object->prev->next = pool_object->next;
00160         } else { 
00161                 pool->obj_allocated_head = pool_object->next;
00162         }
00163         if (pool_object->next) {
00164                 pool_object->next->prev = pool_object->prev;
00165         }
00166         pool_object->next = pool->obj_free_head;
00167         pool_object->prev = NULL;
00168         if (pool->obj_free_head) {
00169                 pool->obj_free_head->prev = pool_object;
00170         } 
00171         pool->obj_allocated_num--;
00172         pool->obj_free_num++;
00173         pool_object->status = TXC_POOL_OBJECT_FREE;
00174         pool->obj_free_head = pool_object; 
00175         if (lock) {
00176                 TXC_MUTEX_UNLOCK(&(pool->mutex));
00177         }       
00178         *objp = NULL;
00179 }
00180 
00181 
00182 txc_pool_object_t *
00183 txc_pool_object_first(txc_pool_t *pool, int obj_status)
00184 {
00185         switch (obj_status) {
00186                 case TXC_POOL_OBJECT_FREE:
00187                         return pool->obj_free_head;
00188                 case TXC_POOL_OBJECT_ALLOCATED:
00189                         return pool->obj_allocated_head;
00190                 case TXC_POOL_OBJECT_ALLOCATED & TXC_POOL_OBJECT_FREE:
00191                         return pool->obj_list;
00192                 default:
00193                         TXC_INTERNALERROR("Unknown status of pool object");
00194         }
00195         return NULL;
00196 }
00197 
00198 
00199 txc_pool_object_t *
00200 txc_pool_object_next(txc_pool_object_t *obj)
00201 {
00202         return obj->next;
00203 }
00204 
00205 
00206 void *
00207 txc_pool_object_of(txc_pool_object_t *obj)
00208 {
00209         return obj->buf;
00210 }
00211 
00212 void
00213 txc_pool_lock(txc_pool_t *pool)
00214 {
00215         TXC_MUTEX_LOCK(&pool->mutex);
00216 }
00217 
00218 
00219 void
00220 txc_pool_unlock(txc_pool_t *pool)
00221 {
00222         TXC_MUTEX_UNLOCK(&pool->mutex);
00223 }
00224 
00225 
00226 
00227 
00228 /*
00229  **************************************************************************
00230  ***                     DEBUGGING SUPPORT ROUTINES                     ***
00231  **************************************************************************
00232  */
00233 
00234 
00235 void 
00236 txc_pool_print(txc_pool_t *pool, txc_pool_object_print_t printer, int verbose) 
00237 {
00238         txc_pool_object_t *pool_object;
00239         unsigned int index;
00240 
00241         if (TXC_DEBUG_POOL) {
00242                 TXC_MUTEX_LOCK(&(pool->mutex));
00243                 fprintf(TXC_DEBUG_OUT, "FREE POOL\n");
00244                 pool_object = pool->obj_free_head;
00245                 while (pool_object) {
00246                         index = (pool_object - pool->obj_list);
00247                         if (verbose) {
00248                                 fprintf(TXC_DEBUG_OUT, "Object Index = %u\t", index);
00249                                 if (pool_object->prev) {
00250                                         index = (pool_object->prev - pool->obj_list);
00251                                         fprintf(TXC_DEBUG_OUT, "[prev = %u, ", index);
00252                                 } else {
00253                                         fprintf(TXC_DEBUG_OUT, "[prev = NULL, ");
00254                                 } 
00255                                 if (pool_object->next) {
00256                                         index = (pool_object->next - pool->obj_list);
00257                                         fprintf(TXC_DEBUG_OUT, "next = %u]\n", index);
00258                                 } else {
00259                                         fprintf(TXC_DEBUG_OUT, "next = NULL]\n");
00260                                 }
00261                         }
00262                         if (printer) {
00263                                 printer(pool_object->buf);
00264                         } 
00265                         pool_object = pool_object->next;
00266                 }
00267                 fprintf(TXC_DEBUG_OUT, "\nALLOCATED POOL\n");
00268                 pool_object = pool->obj_allocated_head;
00269                 while (pool_object) {
00270                         index = (pool_object - pool->obj_list);
00271                         if (verbose) {
00272                                 fprintf(TXC_DEBUG_OUT, "Object Index = %u\t", index);
00273                                 if (pool_object->prev) {
00274                                         index = (pool_object->prev - pool->obj_list);
00275                                         fprintf(TXC_DEBUG_OUT, "[prev = %u, ", index);
00276                                 } else {
00277                                         fprintf(TXC_DEBUG_OUT, "[prev = NULL, ");
00278                                 } 
00279                                 if (pool_object->next) {
00280                                         index = (pool_object->next - pool->obj_list);
00281                                         fprintf(TXC_DEBUG_OUT, "next = %u]\n", index);
00282                                 } else {
00283                                         fprintf(TXC_DEBUG_OUT, "next = NULL]\n");
00284                                 } 
00285                         }
00286                         if (printer) {
00287                                 printer(pool_object->buf);
00288                         } 
00289                         pool_object = pool_object->next;
00290                 }
00291                 TXC_MUTEX_UNLOCK(&(pool->mutex));
00292         }
00293 }

Generated on Wed Dec 9 20:32:39 2009 for xCalls by  doxygen 1.4.7