GNU libmicrohttpd 0.9.5
memorypool.c
Go to the documentation of this file.
00001 /*
00002      This file is part of libmicrohttpd
00003      (C) 2007, 2009, 2010 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 
00038 #define ALIGN_SIZE (2 * sizeof(void*))
00039 
00043 #define ROUND_TO_ALIGN(n) ((n+(ALIGN_SIZE-1)) & (~(ALIGN_SIZE-1)))
00044 
00045 struct MemoryPool
00046 {
00047 
00051   char *memory;
00052 
00056   size_t size;
00057 
00061   size_t pos;
00062 
00066   size_t end;
00067 
00071   int is_mmap;
00072 };
00073 
00079 struct MemoryPool *
00080 MHD_pool_create (size_t max)
00081 {
00082   struct MemoryPool *pool;
00083 
00084   pool = malloc (sizeof (struct MemoryPool));
00085   if (pool == NULL)
00086     return NULL;
00087 #ifdef MAP_ANONYMOUS
00088   pool->memory = MMAP (NULL, max, PROT_READ | PROT_WRITE,
00089                        MAP_ANONYMOUS, -1, 0);
00090 #else
00091   pool->memory = MAP_FAILED;
00092 #endif
00093   if ((pool->memory == MAP_FAILED) || (pool->memory == NULL))
00094     {
00095       pool->memory = malloc (max);
00096       if (pool->memory == NULL)
00097         {
00098           free (pool);
00099           return NULL;
00100         }
00101       pool->is_mmap = MHD_NO;
00102     }
00103   else
00104     {
00105       pool->is_mmap = MHD_YES;
00106     }
00107   pool->pos = 0;
00108   pool->end = max;
00109   pool->size = max;
00110   return pool;
00111 }
00112 
00116 void
00117 MHD_pool_destroy (struct MemoryPool *pool)
00118 {
00119   if (pool == NULL)
00120     return;
00121   if (pool->is_mmap == MHD_NO)
00122     free (pool->memory);
00123   else
00124     MUNMAP (pool->memory, pool->size);
00125   free (pool);
00126 }
00127 
00133 void *
00134 MHD_pool_allocate (struct MemoryPool *pool, 
00135                    size_t size, int from_end)
00136 {
00137   void *ret;
00138 
00139   size = ROUND_TO_ALIGN (size);
00140   if ((pool->pos + size > pool->end) || (pool->pos + size < pool->pos))
00141     return NULL;
00142   if (from_end == MHD_YES)
00143     {
00144       ret = &pool->memory[pool->end - size];
00145       pool->end -= size;
00146     }
00147   else
00148     {
00149       ret = &pool->memory[pool->pos];
00150       pool->pos += size;
00151     }
00152   return ret;
00153 }
00154 
00171 void *
00172 MHD_pool_reallocate (struct MemoryPool *pool,
00173                      void *old, 
00174                      size_t old_size, 
00175                      size_t new_size)
00176 {
00177   void *ret;
00178 
00179   new_size = ROUND_TO_ALIGN (new_size);
00180   if ((pool->end < old_size) || (pool->end < new_size))
00181     return NULL;                /* unsatisfiable or bogus request */
00182 
00183   if ((pool->pos >= old_size) && (&pool->memory[pool->pos - old_size] == old))
00184     {
00185       /* was the previous allocation - optimize! */
00186       if (pool->pos + new_size - old_size <= pool->end)
00187         {
00188           /* fits */
00189           pool->pos += new_size - old_size;
00190           if (new_size < old_size)      /* shrinking - zero again! */
00191             memset (&pool->memory[pool->pos], 0, old_size - new_size);
00192           return old;
00193         }
00194       /* does not fit */
00195       return NULL;
00196     }
00197   if (new_size <= old_size)
00198     return old;                 /* cannot shrink, no need to move */
00199   if ((pool->pos + new_size >= pool->pos) &&
00200       (pool->pos + new_size <= pool->end))
00201     {
00202       /* fits */
00203       ret = &pool->memory[pool->pos];
00204       memcpy (ret, old, old_size);
00205       pool->pos += new_size;
00206       return ret;
00207     }
00208   /* does not fit */
00209   return NULL;
00210 }
00211 
00220 void *
00221 MHD_pool_reset (struct MemoryPool *pool, 
00222                 void *keep, 
00223                 size_t size)
00224 {
00225   size = ROUND_TO_ALIGN (size);
00226   if (keep != NULL)
00227     {
00228       if (keep != pool->memory)
00229         {
00230           memmove (pool->memory, keep, size);
00231           keep = pool->memory;
00232         }
00233       pool->pos = size;
00234     }
00235   pool->end = pool->size;
00236   return keep;
00237 }
00238 
00239 
00240 
00241 /* end of memorypool.c */