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 */