diff -r d59bea55db9b -r c445c931472f src/glpdmp.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/glpdmp.c Mon Dec 06 13:09:21 2010 +0100 @@ -0,0 +1,259 @@ +/* glpdmp.c (dynamic memory pool) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010 Andrew Makhorin, Department for Applied Informatics, +* Moscow Aviation Institute, Moscow, Russia. All rights reserved. +* E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "glpdmp.h" + +#if 1 /* 29/VIII-2008 */ +/* some processors need data to be properly aligned; the macro + align_datasize enlarges the specified size of a data item to provide + a proper alignment of immediately following data */ + +#define align_datasize(size) ((((size) + 7) / 8) * 8) +/* 8 bytes is sufficient in both 32- and 64-bit environments */ +#endif + +#ifdef GLP_DEBUG +struct info +{ DMP *pool; + int size; +}; +#endif + +/*********************************************************************** +* NAME +* +* dmp_create_pool - create dynamic memory pool +* +* SYNOPSIS +* +* #include "glpdmp.h" +* DMP *dmp_create_pool(void); +* +* DESCRIPTION +* +* The routine dmp_create_pool creates a dynamic memory pool. +* +* RETURNS +* +* The routine returns a pointer to the memory pool created. */ + +DMP *dmp_create_pool(void) +{ DMP *pool; + int k; +#ifdef GLP_DEBUG + xprintf("dmp_create_pool: warning: debug mode enabled\n"); +#endif + pool = xmalloc(sizeof(DMP)); +#if 0 + pool->size = 0; +#endif + for (k = 0; k <= 31; k++) pool->avail[k] = NULL; + pool->block = NULL; + pool->used = DMP_BLK_SIZE; + pool->count.lo = pool->count.hi = 0; + return pool; +} + +/*********************************************************************** +* NAME +* +* dmp_get_atom - get free atom from dynamic memory pool +* +* SYNOPSIS +* +* #include "glpdmp.h" +* void *dmp_get_atom(DMP *pool, int size); +* +* DESCRIPTION +* +* The routine dmp_get_atom obtains a free atom (memory block) from the +* specified memory pool. +* +* The parameter size is the atom size, in bytes, 1 <= size <= 256. +* +* Note that the free atom contains arbitrary data, not binary zeros. +* +* RETURNS +* +* The routine returns a pointer to the free atom obtained. */ + +void *dmp_get_atom(DMP *pool, int size) +{ void *atom; + int k; +#ifdef GLP_DEBUG + int orig_size = size; +#endif + if (!(1 <= size && size <= 256)) + xerror("dmp_get_atom: size = %d; invalid atom size\n", size); +#if 0 + if (!(pool->size == 0 || pool->size == size)) + xerror("dmp_get_atom: size = %d; wrong atom size\n", size); +#endif + /* adjust the size to provide the proper data alignment */ + size = align_datasize(size); +#ifdef GLP_DEBUG + size += align_datasize(sizeof(struct info)); +#endif + /* adjust the size to make it multiple of 8 bytes, if needed */ + size = ((size + 7) / 8) * 8; + /* determine the corresponding list of free cells */ + k = size / 8 - 1; + xassert(0 <= k && k <= 31); + /* obtain a free atom */ + if (pool->avail[k] == NULL) + { /* the list of free cells is empty */ + if (pool->used + size > DMP_BLK_SIZE) + { /* allocate a new memory block */ + void *block = xmalloc(DMP_BLK_SIZE); + *(void **)block = pool->block; + pool->block = block; + pool->used = align_datasize(sizeof(void *)); + } + /* place the atom in the current memory block */ + atom = (char *)pool->block + pool->used; + pool->used += size; + } + else + { /* obtain the atom from the list of free cells */ + atom = pool->avail[k]; + pool->avail[k] = *(void **)atom; + } + memset(atom, '?', size); + /* increase the number of atoms which are currently in use */ + pool->count.lo++; + if (pool->count.lo == 0) pool->count.hi++; +#ifdef GLP_DEBUG + ((struct info *)atom)->pool = pool; + ((struct info *)atom)->size = orig_size; + atom = (char *)atom + align_datasize(sizeof(struct info)); +#endif + return atom; +} + +/*********************************************************************** +* NAME +* +* dmp_free_atom - return atom to dynamic memory pool +* +* SYNOPSIS +* +* #include "glpdmp.h" +* void dmp_free_atom(DMP *pool, void *atom, int size); +* +* DESCRIPTION +* +* The routine dmp_free_atom returns the specified atom (memory block) +* to the specified memory pool, making it free. +* +* The parameter size is the atom size, in bytes, 1 <= size <= 256. +* +* Note that the atom can be returned only to the pool, from which it +* was obtained, and its size must be exactly the same as on obtaining +* it from the pool. */ + +void dmp_free_atom(DMP *pool, void *atom, int size) +{ int k; + if (!(1 <= size && size <= 256)) + xerror("dmp_free_atom: size = %d; invalid atom size\n", size); +#if 0 + if (!(pool->size == 0 || pool->size == size)) + xerror("dmp_free_atom: size = %d; wrong atom size\n", size); +#endif + if (pool->count.lo == 0 && pool->count.hi == 0) + xerror("dmp_free_atom: pool allocation error\n"); +#ifdef GLP_DEBUG + atom = (char *)atom - align_datasize(sizeof(struct info)); + xassert(((struct info *)atom)->pool == pool); + xassert(((struct info *)atom)->size == size); +#endif + /* adjust the size to provide the proper data alignment */ + size = align_datasize(size); +#ifdef GLP_DEBUG + size += align_datasize(sizeof(struct info)); +#endif + /* adjust the size to make it multiple of 8 bytes, if needed */ + size = ((size + 7) / 8) * 8; + /* determine the corresponding list of free cells */ + k = size / 8 - 1; + xassert(0 <= k && k <= 31); + /* return the atom to the list of free cells */ + *(void **)atom = pool->avail[k]; + pool->avail[k] = atom; + /* decrease the number of atoms which are currently in use */ + pool->count.lo--; + if (pool->count.lo == 0xFFFFFFFF) pool->count.hi--; + return; +} + +/*********************************************************************** +* NAME +* +* dmp_in_use - determine how many atoms are still in use +* +* SYNOPSIS +* +* #include "glpdmp.h" +* glp_long dmp_in_use(DMP *pool); +* +* DESCRIPTION +* +* The routine dmp_in_use determines how many atoms allocated from the +* specified memory pool with the routine dmp_get_atom are still in use, +* i.e. not returned to the pool with the routine dmp_free_atom. +* +* RETURNS +* +* The routine returns the number of atoms which are still in use. */ + +glp_long dmp_in_use(DMP *pool) +{ return + pool->count; +} + +/*********************************************************************** +* NAME +* +* dmp_delete_pool - delete dynamic memory pool +* +* SYNOPSIS +* +* #include "glpdmp.h" +* void dmp_delete_pool(DMP *pool); +* +* DESCRIPTION +* +* The routine dmp_delete_pool deletes the specified dynamic memory +* pool and frees all the memory allocated to this object. */ + +void dmp_delete_pool(DMP *pool) +{ while (pool->block != NULL) + { void *block = pool->block; + pool->block = *(void **)block; + xfree(block); + } + xfree(pool); + return; +} + +/* eof */