Scippy

SCIP

Solving Constraint Integer Programs

buffer.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2014 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file buffer.c
17  * @brief methods for memory buffers for temporary objects
18  * @author Tobias Achterberg
19  */
20 
21 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
22 
23 #include <assert.h>
24 
25 #include "scip/def.h"
26 #include "scip/pub_message.h"
27 #include "blockmemshell/memory.h"
28 #include "scip/set.h"
29 #include "scip/buffer.h"
30 
31 #include "scip/struct_buffer.h"
32 
33 
34 
35 /** creates memory buffer storage */
37  SCIP_BUFFER** buffer /**< pointer to memory buffer storage */
38  )
39 {
40  assert(buffer != NULL);
41 
42  SCIP_ALLOC( BMSallocMemory(buffer) );
43  (*buffer)->data = NULL;
44  (*buffer)->size = NULL;
45  (*buffer)->used = NULL;
46  (*buffer)->ndata = 0;
47  (*buffer)->firstfree = 0;
48 
49  return SCIP_OKAY;
50 }
51 
52 /** frees memory buffer */
54  SCIP_BUFFER** buffer /**< pointer to memory buffer storage */
55  )
56 {
57  int i;
58 
59  assert(buffer != NULL);
60 
61  for( i = 0; i < (*buffer)->ndata; ++i )
62  {
63  assert(!(*buffer)->used[i]);
64  BMSfreeMemoryArrayNull(&(*buffer)->data[i]);
65  }
66  BMSfreeMemoryArrayNull(&(*buffer)->data);
67  BMSfreeMemoryArrayNull(&(*buffer)->size);
68  BMSfreeMemoryArrayNull(&(*buffer)->used);
69  BMSfreeMemory(buffer);
70 }
71 
72 /** allocates the next unused buffer */
74  SCIP_BUFFER* buffer, /**< memory buffer storage */
75  SCIP_SET* set, /**< global SCIP settings */
76  void** ptr, /**< pointer to store the allocated memory buffer */
77  int size /**< minimal required size of the buffer */
78  )
79 {
80 #ifndef SCIP_NOBUFFERMEM
81  int bufnum;
82 
83  assert(buffer != NULL);
84  assert(buffer->firstfree <= buffer->ndata);
85  assert(ptr != NULL);
86  assert(size >= 0);
87 
88  /* allocate minimal 1 byte */
89  if( size == 0 )
90  size = 1;
91 
92  /* check, if we need additional buffers */
93  if( buffer->firstfree == buffer->ndata )
94  {
95  int newsize;
96  int i;
97 
98  /* create additional buffers */
99  newsize = SCIPsetCalcMemGrowSize(set, buffer->firstfree+1);
100  SCIP_ALLOC( BMSreallocMemoryArray(&buffer->data, newsize) );
101  SCIP_ALLOC( BMSreallocMemoryArray(&buffer->size, newsize) );
102  SCIP_ALLOC( BMSreallocMemoryArray(&buffer->used, newsize) );
103  for( i = buffer->ndata; i < newsize; ++i )
104  {
105  buffer->data[i] = NULL;
106  buffer->size[i] = 0;
107  buffer->used[i] = FALSE;
108  }
109  buffer->ndata = newsize;
110  }
111  assert(buffer->firstfree < buffer->ndata);
112 
113  /* check, if the current buffer is large enough */
114  bufnum = buffer->firstfree;
115  assert(!buffer->used[bufnum]);
116  if( buffer->size[bufnum] < size )
117  {
118  int newsize;
119 
120  /* enlarge buffer */
121  newsize = SCIPsetCalcMemGrowSize(set, size);
122  SCIP_ALLOC( BMSreallocMemorySize(&buffer->data[bufnum], newsize) );
123  buffer->size[bufnum] = newsize;
124  }
125  assert(buffer->size[bufnum] >= size);
126 
127  *ptr = buffer->data[bufnum];
128  buffer->used[bufnum] = TRUE;
129  buffer->firstfree++;
130 
131  SCIPdebugMessage("allocated buffer %d/%d at %p of size %d (required size: %d) for pointer %p\n",
132  bufnum, buffer->ndata, buffer->data[bufnum], buffer->size[bufnum], size, (void*)ptr);
133 
134 #else
135  SCIP_ALLOC( BMSallocMemorySize(ptr, size) );
136 #endif
137 
138  return SCIP_OKAY;
139 }
140 
141 /** allocates the next unused buffer and copies the given memory into the buffer */
143  SCIP_BUFFER* buffer, /**< memory buffer storage */
144  SCIP_SET* set, /**< global SCIP settings */
145  void** ptr, /**< pointer to store the allocated memory buffer */
146  const void* source, /**< memory block to copy into the buffer */
147  int size /**< minimal required size of the buffer */
148  )
149 {
150  assert(source != NULL);
151  assert(size >= 0);
152 
153  /* allocate a buffer of the given size */
154  SCIP_CALL( SCIPbufferAllocMem(buffer, set, ptr, size) );
155 
156  /* copy the source memory into the buffer */
157  BMScopyMemorySize(*ptr, source, size);
158 
159  return SCIP_OKAY;
160 }
161 
162 /** reallocates the buffer to at least the given size */
164  SCIP_BUFFER* buffer, /**< memory buffer storage */
165  SCIP_SET* set, /**< global SCIP settings */
166  void** ptr, /**< pointer to the allocated memory buffer */
167  int size /**< minimal required size of the buffer */
168  )
169 {
170 #ifndef SCIP_NOBUFFERMEM
171  int bufnum;
172 
173  assert(buffer != NULL);
174  assert(buffer->firstfree <= buffer->ndata);
175  assert(ptr != NULL);
176  assert(size >= 0);
177 
178  /* if the pointer doesn't exist yet, allocate it */
179  if( *ptr == NULL )
180  return SCIPbufferAllocMem(buffer, set, ptr, size);
181 
182  assert(buffer->firstfree >= 1);
183 
184  /* Search the pointer in the buffer list
185  * Usually, buffers are allocated and freed like a stack, such that the currently used pointer is
186  * most likely at the end of the buffer list.
187  */
188  for( bufnum = buffer->firstfree-1; bufnum >= 0 && buffer->data[bufnum] != *ptr; --bufnum )
189  {
190  }
191  assert(bufnum >= 0);
192  assert(buffer->data[bufnum] == *ptr);
193  assert(buffer->used[bufnum]);
194  assert(buffer->size[bufnum] >= 1);
195 
196  /* check if the buffer has to be enlarged */
197  if( size > buffer->size[bufnum] )
198  {
199  int newsize;
200 
201  /* enlarge buffer */
202  newsize = SCIPsetCalcMemGrowSize(set, size);
203  SCIP_ALLOC( BMSreallocMemorySize(&buffer->data[bufnum], newsize) );
204  buffer->size[bufnum] = newsize;
205  *ptr = buffer->data[bufnum];
206  }
207  assert(buffer->size[bufnum] >= size);
208  assert(*ptr == buffer->data[bufnum]);
209 
210  SCIPdebugMessage("reallocated buffer %d/%d at %p to size %d (required size: %d) for pointer %p\n",
211  bufnum, buffer->ndata, buffer->data[bufnum], buffer->size[bufnum], size, (void*)ptr);
212 
213 #else
214  assert(ptr != NULL);
215  assert(size >= 0);
216  SCIP_ALLOC( BMSreallocMemorySize(ptr, size) );
217 #endif
218 
219  return SCIP_OKAY;
220 }
221 
222 #ifndef NDEBUG
223 /** allocates the next unused buffer; checks for integer overflow */
225  SCIP_SET* set, /**< global SCIP settings */
226  void** ptr, /**< pointer to store the allocated memory buffer */
227  int num, /**< number of entries to allocate */
228  size_t elemsize /**< size of one element in the array */
229  )
230 {
231  assert( num >= 0 );
232  if( ((size_t)(num)) > (UINT_MAX / elemsize) ) /*lint !e571*/
233  {
234  *ptr = NULL;
235  return SCIP_NOMEMORY;
236  }
237 
238  SCIP_CALL( SCIPbufferAllocMem((set)->buffer, set, (void**)(ptr), (int)(num*elemsize)) );
239 
240  return SCIP_OKAY;
241 }
242 
243 /** allocates the next unused buffer and copies the given memory into the buffer; checks for integer overflows */
245  SCIP_SET* set, /**< global SCIP settings */
246  void** ptr, /**< pointer to store the allocated memory buffer */
247  const void* source, /**< memory block to copy into the buffer */
248  int num, /**< number of entries to copy */
249  size_t elemsize /**< size of one element in the array */
250  )
251 {
252  assert( num >= 0 );
253  if( ((size_t)(num)) > (UINT_MAX / elemsize) ) /*lint !e571*/
254  {
255  *ptr = NULL;
256  return SCIP_NOMEMORY;
257  }
258 
259  SCIP_CALL( SCIPbufferDuplicateMem((set)->buffer, set, (void**)(ptr), source, (int)(num*elemsize)) );
260 
261  return SCIP_OKAY;
262 }
263 
264 /** reallocates the buffer to at least the given size; checks for integer overflows */
266  SCIP_SET* set, /**< global SCIP settings */
267  void** ptr, /**< pointer to the allocated memory buffer */
268  int num, /**< number of entries to get memory for */
269  size_t elemsize /**< size of one element in the array */
270  )
271 {
272  assert( num >= 0 );
273  if( ((size_t)(num)) > (UINT_MAX / elemsize) ) /*lint !e571*/
274  {
275  *ptr = NULL;
276  return SCIP_NOMEMORY;
277  }
278 
279  SCIP_CALL( SCIPbufferReallocMem((set)->buffer, set, (void**)(ptr), (int)(num*elemsize)) );
280 
281  return SCIP_OKAY;
282 }
283 #endif
284 
285 /** frees a buffer */
287  SCIP_BUFFER* buffer, /**< memory buffer storage */
288  void** ptr, /**< pointer to the allocated memory buffer */
289  int dummysize /**< used to get a safer define for SCIPsetFreeBufferSize/Array */
290  )
291 { /*lint --e{715}*/
292 #ifndef SCIP_NOBUFFERMEM
293  int bufnum;
294 
295  assert(buffer != NULL);
296  assert(buffer->firstfree <= buffer->ndata);
297  assert(buffer->firstfree >= 1);
298  assert(dummysize == 0);
299  assert(ptr != NULL);
300 
301  /* Search the pointer in the buffer list
302  * Usually, buffers are allocated and freed like a stack, such that the freed pointer is
303  * most likely at the end of the buffer list.
304  */
305  for( bufnum = buffer->firstfree-1; bufnum >= 0 && buffer->data[bufnum] != *ptr; --bufnum )
306  {
307  }
308  assert(bufnum >= 0);
309  assert(buffer->data[bufnum] == *ptr);
310  assert(buffer->used[bufnum]);
311 
312  *ptr = NULL;
313  buffer->used[bufnum] = FALSE;
314 
315  while( buffer->firstfree > 0 && !buffer->used[buffer->firstfree-1] )
316  buffer->firstfree--;
317 
318  SCIPdebugMessage("freed buffer %d/%d at %p of size %d for pointer %p, first free is %d\n",
319  bufnum, buffer->ndata, buffer->data[bufnum], buffer->size[bufnum], (void*)ptr, buffer->firstfree);
320 
321 #else
322  BMSfreeMemory(ptr);
323 #endif
324 }
325 
326 /** gets number of used buffers */
328  SCIP_BUFFER* buffer /**< memory buffer storage */
329  )
330 {
331  assert(buffer != NULL);
332 
333  return buffer->firstfree;
334 }
335 
336 /** outputs statistics about currently allocated buffers to the screen */
338  SCIP_BUFFER* buffer /**< memory buffer storage */
339  )
340 {
341  int totalmem;
342  int i;
343 
344  assert(buffer != NULL);
345 
346  totalmem = 0;
347  for( i = 0; i < buffer->ndata; ++i )
348  {
349  printf("[%c] %8d bytes at %p\n", buffer->used[i] ? '*' : ' ', buffer->size[i], buffer->data[i]);
350  totalmem += buffer->size[i];
351  }
352  printf(" %8d bytes total in %d buffers\n", totalmem, buffer->ndata);
353 }
#define BMScopyMemorySize(ptr, source, size)
Definition: memory.h:103
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:122
#define NULL
Definition: lpi_spx.cpp:129
#define FALSE
Definition: def.h:52
#define TRUE
Definition: def.h:51
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:4264
#define SCIPdebugMessage
Definition: pub_message.h:77
#define BMSfreeMemory(ptr)
Definition: memory.h:117
SCIP_RETCODE SCIPbufferAllocMem(SCIP_BUFFER *buffer, SCIP_SET *set, void **ptr, int size)
Definition: buffer.c:73
internal methods for memory buffers for temporary objects
SCIP_RETCODE SCIPbufferAllocMemSave(SCIP_SET *set, void **ptr, int num, size_t elemsize)
Definition: buffer.c:224
internal methods for global SCIP settings
#define SCIP_CALL(x)
Definition: def.h:258
void SCIPbufferFreeMem(SCIP_BUFFER *buffer, void **ptr, int dummysize)
Definition: buffer.c:286
SCIP_Bool * used
Definition: struct_buffer.h:40
SCIP_RETCODE SCIPbufferDuplicateMem(SCIP_BUFFER *buffer, SCIP_SET *set, void **ptr, const void *source, int size)
Definition: buffer.c:142
SCIP_RETCODE SCIPbufferCreate(SCIP_BUFFER **buffer)
Definition: buffer.c:36
int SCIPbufferGetNUsed(SCIP_BUFFER *buffer)
Definition: buffer.c:327
void SCIPbufferFree(SCIP_BUFFER **buffer)
Definition: buffer.c:53
SCIP_RETCODE SCIPbufferDuplicateMemSave(SCIP_SET *set, void **ptr, const void *source, int num, size_t elemsize)
Definition: buffer.c:244
void SCIPbufferPrint(SCIP_BUFFER *buffer)
Definition: buffer.c:337
#define BMSallocMemorySize(ptr, size)
Definition: memory.h:93
SCIP_RETCODE SCIPbufferReallocMem(SCIP_BUFFER *buffer, SCIP_SET *set, void **ptr, int size)
Definition: buffer.c:163
public methods for message output
#define BMSreallocMemorySize(ptr, size)
Definition: memory.h:95
void ** data
Definition: struct_buffer.h:38
#define BMSallocMemory(ptr)
Definition: memory.h:92
datastructures for memory buffers for temporary objects
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:80
common defines and data types used in all packages of SCIP
#define SCIP_ALLOC(x)
Definition: def.h:269
SCIP_RETCODE SCIPbufferReallocMemSave(SCIP_SET *set, void **ptr, int num, size_t elemsize)
Definition: buffer.c:265
memory allocation routines