src/glpdmp.c
changeset 1 c445c931472f
equal deleted inserted replaced
-1:000000000000 0:5d29b2d73041
       
     1 /* glpdmp.c (dynamic memory pool) */
       
     2 
       
     3 /***********************************************************************
       
     4 *  This code is part of GLPK (GNU Linear Programming Kit).
       
     5 *
       
     6 *  Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
       
     7 *  2009, 2010 Andrew Makhorin, Department for Applied Informatics,
       
     8 *  Moscow Aviation Institute, Moscow, Russia. All rights reserved.
       
     9 *  E-mail: <mao@gnu.org>.
       
    10 *
       
    11 *  GLPK is free software: you can redistribute it and/or modify it
       
    12 *  under the terms of the GNU General Public License as published by
       
    13 *  the Free Software Foundation, either version 3 of the License, or
       
    14 *  (at your option) any later version.
       
    15 *
       
    16 *  GLPK is distributed in the hope that it will be useful, but WITHOUT
       
    17 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
       
    18 *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
       
    19 *  License for more details.
       
    20 *
       
    21 *  You should have received a copy of the GNU General Public License
       
    22 *  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
       
    23 ***********************************************************************/
       
    24 
       
    25 #include "glpdmp.h"
       
    26 
       
    27 #if 1 /* 29/VIII-2008 */
       
    28 /* some processors need data to be properly aligned; the macro
       
    29    align_datasize enlarges the specified size of a data item to provide
       
    30    a proper alignment of immediately following data */
       
    31 
       
    32 #define align_datasize(size) ((((size) + 7) / 8) * 8)
       
    33 /* 8 bytes is sufficient in both 32- and 64-bit environments */
       
    34 #endif
       
    35 
       
    36 #ifdef GLP_DEBUG
       
    37 struct info
       
    38 {     DMP *pool;
       
    39       int size;
       
    40 };
       
    41 #endif
       
    42 
       
    43 /***********************************************************************
       
    44 *  NAME
       
    45 *
       
    46 *  dmp_create_pool - create dynamic memory pool
       
    47 *
       
    48 *  SYNOPSIS
       
    49 *
       
    50 *  #include "glpdmp.h"
       
    51 *  DMP *dmp_create_pool(void);
       
    52 *
       
    53 *  DESCRIPTION
       
    54 *
       
    55 *  The routine dmp_create_pool creates a dynamic memory pool.
       
    56 *
       
    57 *  RETURNS
       
    58 *
       
    59 *  The routine returns a pointer to the memory pool created. */
       
    60 
       
    61 DMP *dmp_create_pool(void)
       
    62 {     DMP *pool;
       
    63       int k;
       
    64 #ifdef GLP_DEBUG
       
    65       xprintf("dmp_create_pool: warning: debug mode enabled\n");
       
    66 #endif
       
    67       pool = xmalloc(sizeof(DMP));
       
    68 #if 0
       
    69       pool->size = 0;
       
    70 #endif
       
    71       for (k = 0; k <= 31; k++) pool->avail[k] = NULL;
       
    72       pool->block = NULL;
       
    73       pool->used = DMP_BLK_SIZE;
       
    74       pool->count.lo = pool->count.hi = 0;
       
    75       return pool;
       
    76 }
       
    77 
       
    78 /***********************************************************************
       
    79 *  NAME
       
    80 *
       
    81 *  dmp_get_atom - get free atom from dynamic memory pool
       
    82 *
       
    83 *  SYNOPSIS
       
    84 *
       
    85 *  #include "glpdmp.h"
       
    86 *  void *dmp_get_atom(DMP *pool, int size);
       
    87 *
       
    88 *  DESCRIPTION
       
    89 *
       
    90 *  The routine dmp_get_atom obtains a free atom (memory block) from the
       
    91 *  specified memory pool.
       
    92 *
       
    93 *  The parameter size is the atom size, in bytes, 1 <= size <= 256.
       
    94 *
       
    95 *  Note that the free atom contains arbitrary data, not binary zeros.
       
    96 *
       
    97 *  RETURNS
       
    98 *
       
    99 *  The routine returns a pointer to the free atom obtained. */
       
   100 
       
   101 void *dmp_get_atom(DMP *pool, int size)
       
   102 {     void *atom;
       
   103       int k;
       
   104 #ifdef GLP_DEBUG
       
   105       int orig_size = size;
       
   106 #endif
       
   107       if (!(1 <= size && size <= 256))
       
   108          xerror("dmp_get_atom: size = %d; invalid atom size\n", size);
       
   109 #if 0
       
   110       if (!(pool->size == 0 || pool->size == size))
       
   111          xerror("dmp_get_atom: size = %d; wrong atom size\n", size);
       
   112 #endif
       
   113       /* adjust the size to provide the proper data alignment */
       
   114       size = align_datasize(size);
       
   115 #ifdef GLP_DEBUG
       
   116       size += align_datasize(sizeof(struct info));
       
   117 #endif
       
   118       /* adjust the size to make it multiple of 8 bytes, if needed */
       
   119       size = ((size + 7) / 8) * 8;
       
   120       /* determine the corresponding list of free cells */
       
   121       k = size / 8 - 1;
       
   122       xassert(0 <= k && k <= 31);
       
   123       /* obtain a free atom */
       
   124       if (pool->avail[k] == NULL)
       
   125       {  /* the list of free cells is empty */
       
   126          if (pool->used + size > DMP_BLK_SIZE)
       
   127          {  /* allocate a new memory block */
       
   128             void *block = xmalloc(DMP_BLK_SIZE);
       
   129             *(void **)block = pool->block;
       
   130             pool->block = block;
       
   131             pool->used = align_datasize(sizeof(void *));
       
   132          }
       
   133          /* place the atom in the current memory block */
       
   134          atom = (char *)pool->block + pool->used;
       
   135          pool->used += size;
       
   136       }
       
   137       else
       
   138       {  /* obtain the atom from the list of free cells */
       
   139          atom = pool->avail[k];
       
   140          pool->avail[k] = *(void **)atom;
       
   141       }
       
   142       memset(atom, '?', size);
       
   143       /* increase the number of atoms which are currently in use */
       
   144       pool->count.lo++;
       
   145       if (pool->count.lo == 0) pool->count.hi++;
       
   146 #ifdef GLP_DEBUG
       
   147       ((struct info *)atom)->pool = pool;
       
   148       ((struct info *)atom)->size = orig_size;
       
   149       atom = (char *)atom + align_datasize(sizeof(struct info));
       
   150 #endif
       
   151       return atom;
       
   152 }
       
   153 
       
   154 /***********************************************************************
       
   155 *  NAME
       
   156 *
       
   157 *  dmp_free_atom - return atom to dynamic memory pool
       
   158 *
       
   159 *  SYNOPSIS
       
   160 *
       
   161 *  #include "glpdmp.h"
       
   162 *  void dmp_free_atom(DMP *pool, void *atom, int size);
       
   163 *
       
   164 *  DESCRIPTION
       
   165 *
       
   166 *  The routine dmp_free_atom returns the specified atom (memory block)
       
   167 *  to the specified memory pool, making it free.
       
   168 *
       
   169 *  The parameter size is the atom size, in bytes, 1 <= size <= 256.
       
   170 *
       
   171 *  Note that the atom can be returned only to the pool, from which it
       
   172 *  was obtained, and its size must be exactly the same as on obtaining
       
   173 *  it from the pool. */
       
   174 
       
   175 void dmp_free_atom(DMP *pool, void *atom, int size)
       
   176 {     int k;
       
   177       if (!(1 <= size && size <= 256))
       
   178          xerror("dmp_free_atom: size = %d; invalid atom size\n", size);
       
   179 #if 0
       
   180       if (!(pool->size == 0 || pool->size == size))
       
   181          xerror("dmp_free_atom: size = %d; wrong atom size\n", size);
       
   182 #endif
       
   183       if (pool->count.lo == 0 && pool->count.hi == 0)
       
   184          xerror("dmp_free_atom: pool allocation error\n");
       
   185 #ifdef GLP_DEBUG
       
   186       atom = (char *)atom - align_datasize(sizeof(struct info));
       
   187       xassert(((struct info *)atom)->pool == pool);
       
   188       xassert(((struct info *)atom)->size == size);
       
   189 #endif
       
   190       /* adjust the size to provide the proper data alignment */
       
   191       size = align_datasize(size);
       
   192 #ifdef GLP_DEBUG
       
   193       size += align_datasize(sizeof(struct info));
       
   194 #endif
       
   195       /* adjust the size to make it multiple of 8 bytes, if needed */
       
   196       size = ((size + 7) / 8) * 8;
       
   197       /* determine the corresponding list of free cells */
       
   198       k = size / 8 - 1;
       
   199       xassert(0 <= k && k <= 31);
       
   200       /* return the atom to the list of free cells */
       
   201       *(void **)atom = pool->avail[k];
       
   202       pool->avail[k] = atom;
       
   203       /* decrease the number of atoms which are currently in use */
       
   204       pool->count.lo--;
       
   205       if (pool->count.lo == 0xFFFFFFFF) pool->count.hi--;
       
   206       return;
       
   207 }
       
   208 
       
   209 /***********************************************************************
       
   210 *  NAME
       
   211 *
       
   212 *  dmp_in_use - determine how many atoms are still in use
       
   213 *
       
   214 *  SYNOPSIS
       
   215 *
       
   216 *  #include "glpdmp.h"
       
   217 *  glp_long dmp_in_use(DMP *pool);
       
   218 *
       
   219 *  DESCRIPTION
       
   220 *
       
   221 *  The routine dmp_in_use determines how many atoms allocated from the
       
   222 *  specified memory pool with the routine dmp_get_atom are still in use,
       
   223 *  i.e. not returned to the pool with the routine dmp_free_atom.
       
   224 *
       
   225 *  RETURNS
       
   226 *
       
   227 *  The routine returns the number of atoms which are still in use. */
       
   228 
       
   229 glp_long dmp_in_use(DMP *pool)
       
   230 {     return
       
   231          pool->count;
       
   232 }
       
   233 
       
   234 /***********************************************************************
       
   235 *  NAME
       
   236 *
       
   237 *  dmp_delete_pool - delete dynamic memory pool
       
   238 *
       
   239 *  SYNOPSIS
       
   240 *
       
   241 *  #include "glpdmp.h"
       
   242 *  void dmp_delete_pool(DMP *pool);
       
   243 *
       
   244 *  DESCRIPTION
       
   245 *
       
   246 *  The routine dmp_delete_pool deletes the specified dynamic memory
       
   247 *  pool and frees all the memory allocated to this object. */
       
   248 
       
   249 void dmp_delete_pool(DMP *pool)
       
   250 {     while (pool->block != NULL)
       
   251       {  void *block = pool->block;
       
   252          pool->block = *(void **)block;
       
   253          xfree(block);
       
   254       }
       
   255       xfree(pool);
       
   256       return;
       
   257 }
       
   258 
       
   259 /* eof */