src/glpdmp.c
changeset 1 c445c931472f
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/glpdmp.c	Mon Dec 06 13:09:21 2010 +0100
     1.3 @@ -0,0 +1,259 @@
     1.4 +/* glpdmp.c (dynamic memory pool) */
     1.5 +
     1.6 +/***********************************************************************
     1.7 +*  This code is part of GLPK (GNU Linear Programming Kit).
     1.8 +*
     1.9 +*  Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
    1.10 +*  2009, 2010 Andrew Makhorin, Department for Applied Informatics,
    1.11 +*  Moscow Aviation Institute, Moscow, Russia. All rights reserved.
    1.12 +*  E-mail: <mao@gnu.org>.
    1.13 +*
    1.14 +*  GLPK is free software: you can redistribute it and/or modify it
    1.15 +*  under the terms of the GNU General Public License as published by
    1.16 +*  the Free Software Foundation, either version 3 of the License, or
    1.17 +*  (at your option) any later version.
    1.18 +*
    1.19 +*  GLPK is distributed in the hope that it will be useful, but WITHOUT
    1.20 +*  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    1.21 +*  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
    1.22 +*  License for more details.
    1.23 +*
    1.24 +*  You should have received a copy of the GNU General Public License
    1.25 +*  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
    1.26 +***********************************************************************/
    1.27 +
    1.28 +#include "glpdmp.h"
    1.29 +
    1.30 +#if 1 /* 29/VIII-2008 */
    1.31 +/* some processors need data to be properly aligned; the macro
    1.32 +   align_datasize enlarges the specified size of a data item to provide
    1.33 +   a proper alignment of immediately following data */
    1.34 +
    1.35 +#define align_datasize(size) ((((size) + 7) / 8) * 8)
    1.36 +/* 8 bytes is sufficient in both 32- and 64-bit environments */
    1.37 +#endif
    1.38 +
    1.39 +#ifdef GLP_DEBUG
    1.40 +struct info
    1.41 +{     DMP *pool;
    1.42 +      int size;
    1.43 +};
    1.44 +#endif
    1.45 +
    1.46 +/***********************************************************************
    1.47 +*  NAME
    1.48 +*
    1.49 +*  dmp_create_pool - create dynamic memory pool
    1.50 +*
    1.51 +*  SYNOPSIS
    1.52 +*
    1.53 +*  #include "glpdmp.h"
    1.54 +*  DMP *dmp_create_pool(void);
    1.55 +*
    1.56 +*  DESCRIPTION
    1.57 +*
    1.58 +*  The routine dmp_create_pool creates a dynamic memory pool.
    1.59 +*
    1.60 +*  RETURNS
    1.61 +*
    1.62 +*  The routine returns a pointer to the memory pool created. */
    1.63 +
    1.64 +DMP *dmp_create_pool(void)
    1.65 +{     DMP *pool;
    1.66 +      int k;
    1.67 +#ifdef GLP_DEBUG
    1.68 +      xprintf("dmp_create_pool: warning: debug mode enabled\n");
    1.69 +#endif
    1.70 +      pool = xmalloc(sizeof(DMP));
    1.71 +#if 0
    1.72 +      pool->size = 0;
    1.73 +#endif
    1.74 +      for (k = 0; k <= 31; k++) pool->avail[k] = NULL;
    1.75 +      pool->block = NULL;
    1.76 +      pool->used = DMP_BLK_SIZE;
    1.77 +      pool->count.lo = pool->count.hi = 0;
    1.78 +      return pool;
    1.79 +}
    1.80 +
    1.81 +/***********************************************************************
    1.82 +*  NAME
    1.83 +*
    1.84 +*  dmp_get_atom - get free atom from dynamic memory pool
    1.85 +*
    1.86 +*  SYNOPSIS
    1.87 +*
    1.88 +*  #include "glpdmp.h"
    1.89 +*  void *dmp_get_atom(DMP *pool, int size);
    1.90 +*
    1.91 +*  DESCRIPTION
    1.92 +*
    1.93 +*  The routine dmp_get_atom obtains a free atom (memory block) from the
    1.94 +*  specified memory pool.
    1.95 +*
    1.96 +*  The parameter size is the atom size, in bytes, 1 <= size <= 256.
    1.97 +*
    1.98 +*  Note that the free atom contains arbitrary data, not binary zeros.
    1.99 +*
   1.100 +*  RETURNS
   1.101 +*
   1.102 +*  The routine returns a pointer to the free atom obtained. */
   1.103 +
   1.104 +void *dmp_get_atom(DMP *pool, int size)
   1.105 +{     void *atom;
   1.106 +      int k;
   1.107 +#ifdef GLP_DEBUG
   1.108 +      int orig_size = size;
   1.109 +#endif
   1.110 +      if (!(1 <= size && size <= 256))
   1.111 +         xerror("dmp_get_atom: size = %d; invalid atom size\n", size);
   1.112 +#if 0
   1.113 +      if (!(pool->size == 0 || pool->size == size))
   1.114 +         xerror("dmp_get_atom: size = %d; wrong atom size\n", size);
   1.115 +#endif
   1.116 +      /* adjust the size to provide the proper data alignment */
   1.117 +      size = align_datasize(size);
   1.118 +#ifdef GLP_DEBUG
   1.119 +      size += align_datasize(sizeof(struct info));
   1.120 +#endif
   1.121 +      /* adjust the size to make it multiple of 8 bytes, if needed */
   1.122 +      size = ((size + 7) / 8) * 8;
   1.123 +      /* determine the corresponding list of free cells */
   1.124 +      k = size / 8 - 1;
   1.125 +      xassert(0 <= k && k <= 31);
   1.126 +      /* obtain a free atom */
   1.127 +      if (pool->avail[k] == NULL)
   1.128 +      {  /* the list of free cells is empty */
   1.129 +         if (pool->used + size > DMP_BLK_SIZE)
   1.130 +         {  /* allocate a new memory block */
   1.131 +            void *block = xmalloc(DMP_BLK_SIZE);
   1.132 +            *(void **)block = pool->block;
   1.133 +            pool->block = block;
   1.134 +            pool->used = align_datasize(sizeof(void *));
   1.135 +         }
   1.136 +         /* place the atom in the current memory block */
   1.137 +         atom = (char *)pool->block + pool->used;
   1.138 +         pool->used += size;
   1.139 +      }
   1.140 +      else
   1.141 +      {  /* obtain the atom from the list of free cells */
   1.142 +         atom = pool->avail[k];
   1.143 +         pool->avail[k] = *(void **)atom;
   1.144 +      }
   1.145 +      memset(atom, '?', size);
   1.146 +      /* increase the number of atoms which are currently in use */
   1.147 +      pool->count.lo++;
   1.148 +      if (pool->count.lo == 0) pool->count.hi++;
   1.149 +#ifdef GLP_DEBUG
   1.150 +      ((struct info *)atom)->pool = pool;
   1.151 +      ((struct info *)atom)->size = orig_size;
   1.152 +      atom = (char *)atom + align_datasize(sizeof(struct info));
   1.153 +#endif
   1.154 +      return atom;
   1.155 +}
   1.156 +
   1.157 +/***********************************************************************
   1.158 +*  NAME
   1.159 +*
   1.160 +*  dmp_free_atom - return atom to dynamic memory pool
   1.161 +*
   1.162 +*  SYNOPSIS
   1.163 +*
   1.164 +*  #include "glpdmp.h"
   1.165 +*  void dmp_free_atom(DMP *pool, void *atom, int size);
   1.166 +*
   1.167 +*  DESCRIPTION
   1.168 +*
   1.169 +*  The routine dmp_free_atom returns the specified atom (memory block)
   1.170 +*  to the specified memory pool, making it free.
   1.171 +*
   1.172 +*  The parameter size is the atom size, in bytes, 1 <= size <= 256.
   1.173 +*
   1.174 +*  Note that the atom can be returned only to the pool, from which it
   1.175 +*  was obtained, and its size must be exactly the same as on obtaining
   1.176 +*  it from the pool. */
   1.177 +
   1.178 +void dmp_free_atom(DMP *pool, void *atom, int size)
   1.179 +{     int k;
   1.180 +      if (!(1 <= size && size <= 256))
   1.181 +         xerror("dmp_free_atom: size = %d; invalid atom size\n", size);
   1.182 +#if 0
   1.183 +      if (!(pool->size == 0 || pool->size == size))
   1.184 +         xerror("dmp_free_atom: size = %d; wrong atom size\n", size);
   1.185 +#endif
   1.186 +      if (pool->count.lo == 0 && pool->count.hi == 0)
   1.187 +         xerror("dmp_free_atom: pool allocation error\n");
   1.188 +#ifdef GLP_DEBUG
   1.189 +      atom = (char *)atom - align_datasize(sizeof(struct info));
   1.190 +      xassert(((struct info *)atom)->pool == pool);
   1.191 +      xassert(((struct info *)atom)->size == size);
   1.192 +#endif
   1.193 +      /* adjust the size to provide the proper data alignment */
   1.194 +      size = align_datasize(size);
   1.195 +#ifdef GLP_DEBUG
   1.196 +      size += align_datasize(sizeof(struct info));
   1.197 +#endif
   1.198 +      /* adjust the size to make it multiple of 8 bytes, if needed */
   1.199 +      size = ((size + 7) / 8) * 8;
   1.200 +      /* determine the corresponding list of free cells */
   1.201 +      k = size / 8 - 1;
   1.202 +      xassert(0 <= k && k <= 31);
   1.203 +      /* return the atom to the list of free cells */
   1.204 +      *(void **)atom = pool->avail[k];
   1.205 +      pool->avail[k] = atom;
   1.206 +      /* decrease the number of atoms which are currently in use */
   1.207 +      pool->count.lo--;
   1.208 +      if (pool->count.lo == 0xFFFFFFFF) pool->count.hi--;
   1.209 +      return;
   1.210 +}
   1.211 +
   1.212 +/***********************************************************************
   1.213 +*  NAME
   1.214 +*
   1.215 +*  dmp_in_use - determine how many atoms are still in use
   1.216 +*
   1.217 +*  SYNOPSIS
   1.218 +*
   1.219 +*  #include "glpdmp.h"
   1.220 +*  glp_long dmp_in_use(DMP *pool);
   1.221 +*
   1.222 +*  DESCRIPTION
   1.223 +*
   1.224 +*  The routine dmp_in_use determines how many atoms allocated from the
   1.225 +*  specified memory pool with the routine dmp_get_atom are still in use,
   1.226 +*  i.e. not returned to the pool with the routine dmp_free_atom.
   1.227 +*
   1.228 +*  RETURNS
   1.229 +*
   1.230 +*  The routine returns the number of atoms which are still in use. */
   1.231 +
   1.232 +glp_long dmp_in_use(DMP *pool)
   1.233 +{     return
   1.234 +         pool->count;
   1.235 +}
   1.236 +
   1.237 +/***********************************************************************
   1.238 +*  NAME
   1.239 +*
   1.240 +*  dmp_delete_pool - delete dynamic memory pool
   1.241 +*
   1.242 +*  SYNOPSIS
   1.243 +*
   1.244 +*  #include "glpdmp.h"
   1.245 +*  void dmp_delete_pool(DMP *pool);
   1.246 +*
   1.247 +*  DESCRIPTION
   1.248 +*
   1.249 +*  The routine dmp_delete_pool deletes the specified dynamic memory
   1.250 +*  pool and frees all the memory allocated to this object. */
   1.251 +
   1.252 +void dmp_delete_pool(DMP *pool)
   1.253 +{     while (pool->block != NULL)
   1.254 +      {  void *block = pool->block;
   1.255 +         pool->block = *(void **)block;
   1.256 +         xfree(block);
   1.257 +      }
   1.258 +      xfree(pool);
   1.259 +      return;
   1.260 +}
   1.261 +
   1.262 +/* eof */