memorypool.c

Go to the documentation of this file.
00001 /*
00002      This file is part of libmicrohttpd
00003      (C) 2007, 2009 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   size_t size;
00048 
00052   size_t pos;
00053 
00057   size_t end;
00058 
00062   int is_mmap;
00063 };
00064 
00070 struct MemoryPool *
00071 MHD_pool_create (size_t 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, 
00126                    size_t size, int from_end)
00127 {
00128   void *ret;
00129 
00130   if ((pool->pos + size > pool->end) || (pool->pos + size < pool->pos))
00131     return NULL;
00132   if (from_end == MHD_YES)
00133     {
00134       ret = &pool->memory[pool->end - size];
00135       pool->end -= size;
00136     }
00137   else
00138     {
00139       ret = &pool->memory[pool->pos];
00140       pool->pos += size;
00141     }
00142   return ret;
00143 }
00144 
00161 void *
00162 MHD_pool_reallocate (struct MemoryPool *pool,
00163                      void *old, 
00164                      size_t old_size, 
00165                      size_t new_size)
00166 {
00167   void *ret;
00168 
00169   if ((pool->end < old_size) || (pool->end < new_size))
00170     return NULL;                /* unsatisfiable or bogus request */
00171 
00172   if ((pool->pos >= old_size) && (&pool->memory[pool->pos - old_size] == old))
00173     {
00174       /* was the previous allocation - optimize! */
00175       if (pool->pos + new_size - old_size <= pool->end)
00176         {
00177           /* fits */
00178           pool->pos += new_size - old_size;
00179           if (new_size < old_size)      /* shrinking - zero again! */
00180             memset (&pool->memory[pool->pos], 0, old_size - new_size);
00181           return old;
00182         }
00183       /* does not fit */
00184       return NULL;
00185     }
00186   if (new_size <= old_size)
00187     return old;                 /* cannot shrink, no need to move */
00188   if ((pool->pos + new_size >= pool->pos) &&
00189       (pool->pos + new_size <= pool->end))
00190     {
00191       /* fits */
00192       ret = &pool->memory[pool->pos];
00193       memcpy (ret, old, old_size);
00194       pool->pos += new_size;
00195       return ret;
00196     }
00197   /* does not fit */
00198   return NULL;
00199 }
00200 
00209 void *
00210 MHD_pool_reset (struct MemoryPool *pool, 
00211                 void *keep, 
00212                 size_t size)
00213 {
00214   if (keep != NULL)
00215     {
00216       if (keep != pool->memory)
00217         {
00218           memmove (pool->memory, keep, size);
00219           keep = pool->memory;
00220         }
00221       pool->pos = size;
00222     }
00223   pool->end = pool->size;
00224   return keep;
00225 }
00226 
00227 
00228 
00229 /* end of memorypool.c */

Generated on Fri Feb 27 18:32:19 2009 for GNU libmicrohttpd by  doxygen 1.5.7.1