memorypool.c

Go to the documentation of this file.
00001 /*
00002      This file is part of libmicrohttpd
00003      (C) 2007 Daniel Pittman and Christian Grothoff
00004 
00005      This library is free software; you can redistribute it and/or
00006      modify it under the terms of the GNU Lesser General Public
00007      License as published by the Free Software Foundation; either
00008      version 2.1 of the License, or (at your option) any later version.
00009 
00010      This library is distributed in the hope that it will be useful,
00011      but WITHOUT ANY WARRANTY; without even the implied warranty of
00012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013      Lesser General Public License for more details.
00014 
00015      You should have received a copy of the GNU Lesser General Public
00016      License along with this library; if not, write to the Free Software
00017      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00018 */
00019 
00025 #include "memorypool.h"
00026 
00027 /* define MAP_ANONYMOUS for Mac OS X */
00028 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
00029 #define MAP_ANONYMOUS MAP_ANON
00030 #endif
00031 #ifndef MAP_FAILED
00032 #define MAP_FAILED ((void*)-1)
00033 #endif
00034 
00035 
00036 struct MemoryPool
00037 {
00038 
00042   char *memory;
00043 
00047   unsigned int size;
00048 
00052   unsigned int pos;
00053 
00057   unsigned int end;
00058 
00062   int is_mmap;
00063 };
00064 
00070 struct MemoryPool *
00071 MHD_pool_create (unsigned int max)
00072 {
00073   struct MemoryPool *pool;
00074 
00075   pool = malloc (sizeof (struct MemoryPool));
00076   if (pool == NULL)
00077     return NULL;
00078 #ifdef MAP_ANONYMOUS
00079   pool->memory = MMAP (NULL, max, PROT_READ | PROT_WRITE,
00080                        MAP_ANONYMOUS, -1, 0);
00081 #else
00082   pool->memory = MAP_FAILED;
00083 #endif
00084   if ((pool->memory == MAP_FAILED) || (pool->memory == NULL))
00085     {
00086       pool->memory = malloc (max);
00087       if (pool->memory == NULL)
00088         {
00089           free (pool);
00090           return NULL;
00091         }
00092       pool->is_mmap = MHD_NO;
00093     }
00094   else
00095     {
00096       pool->is_mmap = MHD_YES;
00097     }
00098   pool->pos = 0;
00099   pool->end = max;
00100   pool->size = max;
00101   return pool;
00102 }
00103 
00107 void
00108 MHD_pool_destroy (struct MemoryPool *pool)
00109 {
00110   if (pool == NULL)
00111     return;
00112   if (pool->is_mmap == MHD_NO)
00113     free (pool->memory);
00114   else
00115     MUNMAP (pool->memory, pool->size);
00116   free (pool);
00117 }
00118 
00124 void *
00125 MHD_pool_allocate (struct MemoryPool *pool, unsigned int size, int from_end)
00126 {
00127   void *ret;
00128 
00129   if ((pool->pos + size > pool->end) || (pool->pos + size < pool->pos))
00130     return NULL;
00131   if (from_end == MHD_YES)
00132     {
00133       ret = &pool->memory[pool->end - size];
00134       pool->end -= size;
00135     }
00136   else
00137     {
00138       ret = &pool->memory[pool->pos];
00139       pool->pos += size;
00140     }
00141   return ret;
00142 }
00143 
00160 void *
00161 MHD_pool_reallocate (struct MemoryPool *pool,
00162                      void *old, unsigned int old_size, unsigned int new_size)
00163 {
00164   void *ret;
00165 
00166   if ((pool->end < old_size) || (pool->end < new_size))
00167     return NULL;                /* unsatisfiable or bogus request */
00168 
00169   if ((pool->pos >= old_size) && (&pool->memory[pool->pos - old_size] == old))
00170     {
00171       /* was the previous allocation - optimize! */
00172       if (pool->pos + new_size - old_size <= pool->end)
00173         {
00174           /* fits */
00175           pool->pos += new_size - old_size;
00176           if (new_size < old_size)      /* shrinking - zero again! */
00177             memset (&pool->memory[pool->pos], 0, old_size - new_size);
00178           return old;
00179         }
00180       /* does not fit */
00181       return NULL;
00182     }
00183   if (new_size <= old_size)
00184     return old;                 /* cannot shrink, no need to move */
00185   if ((pool->pos + new_size >= pool->pos) &&
00186       (pool->pos + new_size <= pool->end))
00187     {
00188       /* fits */
00189       ret = &pool->memory[pool->pos];
00190       memcpy (ret, old, old_size);
00191       pool->pos += new_size;
00192       return ret;
00193     }
00194   /* does not fit */
00195   return NULL;
00196 }
00197 
00206 void *
00207 MHD_pool_reset (struct MemoryPool *pool, void *keep, unsigned int size)
00208 {
00209   if (keep != NULL)
00210     {
00211       if (keep != pool->memory)
00212         {
00213           memmove (pool->memory, keep, size);
00214           keep = pool->memory;
00215         }
00216       pool->pos = size;
00217     }
00218   pool->end = pool->size;
00219   return keep;
00220 }
00221 
00222 
00223 
00224 /* end of memorypool.c */

Generated on Sun Nov 16 16:53:06 2008 for GNU libmicrohttpd by  doxygen 1.5.1