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 
00026 #include "memorypool.h"
00027 
00028 /* define MAP_ANONYMOUS for Mac OS X */
00029 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
00030 #define MAP_ANONYMOUS MAP_ANON
00031 #endif
00032 
00033 struct MemoryPool
00034 {
00035 
00039   char *memory;
00040 
00044   unsigned int size;
00045 
00049   unsigned int pos;
00050 
00054   unsigned int end;
00055 
00059   int is_mmap;
00060 };
00061 
00067 struct MemoryPool *
00068 MHD_pool_create (unsigned int max)
00069 {
00070   struct MemoryPool *pool;
00071 
00072   pool = malloc (sizeof (struct MemoryPool));
00073   if (pool == NULL)
00074     return NULL;
00075   pool->memory = MMAP (NULL, max, PROT_READ | PROT_WRITE,
00076                        MAP_ANONYMOUS, -1, 0);
00077   if ((pool->memory == MAP_FAILED) || (pool->memory == NULL))
00078     {
00079       pool->memory = malloc (max);
00080       if (pool->memory == NULL)
00081         {
00082           free (pool);
00083           return NULL;
00084         }
00085       pool->is_mmap = MHD_NO;
00086     }
00087   else
00088     {
00089       pool->is_mmap = MHD_YES;
00090     }
00091   pool->pos = 0;
00092   pool->end = max;
00093   pool->size = max;
00094   return pool;
00095 }
00096 
00100 void
00101 MHD_pool_destroy (struct MemoryPool *pool)
00102 {
00103   if (pool == NULL)
00104     return;
00105   if (pool->is_mmap == MHD_NO)
00106     free (pool->memory);
00107   else
00108     MUNMAP (pool->memory, pool->size);
00109   free (pool);
00110 }
00111 
00117 void *
00118 MHD_pool_allocate (struct MemoryPool *pool, unsigned int size, int from_end)
00119 {
00120   void *ret;
00121 
00122   if ((pool->pos + size > pool->end) || (pool->pos + size < pool->pos))
00123     return NULL;
00124   if (from_end == MHD_YES)
00125     {
00126       ret = &pool->memory[pool->end - size];
00127       pool->end -= size;
00128     }
00129   else
00130     {
00131       ret = &pool->memory[pool->pos];
00132       pool->pos += size;
00133     }
00134   return ret;
00135 }
00136 
00153 void *
00154 MHD_pool_reallocate (struct MemoryPool *pool,
00155                      void *old, unsigned int old_size, unsigned int new_size)
00156 {
00157   void *ret;
00158 
00159   if ((pool->end < old_size) || (pool->end < new_size))
00160     return NULL;                /* unsatisfiable or bogus request */
00161 
00162   if ((pool->pos >= old_size) && (&pool->memory[pool->pos - old_size] == old))
00163     {
00164       /* was the previous allocation - optimize! */
00165       if (pool->pos + new_size - old_size <= pool->end)
00166         {
00167           /* fits */
00168           pool->pos += new_size - old_size;
00169           if (new_size < old_size)      /* shrinking - zero again! */
00170             memset (&pool->memory[pool->pos], 0, old_size - new_size);
00171           return old;
00172         }
00173       /* does not fit */
00174       return NULL;
00175     }
00176   if (new_size <= old_size)
00177     return old;                 /* cannot shrink, no need to move */
00178   if ((pool->pos + new_size >= pool->pos) &&
00179       (pool->pos + new_size <= pool->end))
00180     {
00181       /* fits */
00182       ret = &pool->memory[pool->pos];
00183       memcpy (ret, old, old_size);
00184       pool->pos += new_size;
00185       return ret;
00186     }
00187   /* does not fit */
00188   return NULL;
00189 }
00190 
00199 void *
00200 MHD_pool_reset (struct MemoryPool *pool, void *keep, unsigned int size)
00201 {
00202   if (keep != NULL)
00203     {
00204       if (keep != pool->memory)
00205         {
00206           memmove (pool->memory, keep, size);
00207           keep = pool->memory;
00208         }
00209       pool->pos = size;
00210     }
00211   pool->end = pool->size;
00212   return keep;
00213 }
00214 
00215 
00216 
00217 /* end of memorypool.c */

Generated on Fri Oct 3 15:57:41 2008 for GNU libmicrohttpd by  doxygen 1.5.6