1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /*                                                                           */
3 /*                  This file is part of the library                         */
4 /*          BMS --- Block Memory Shell                                       */
5 /*                                                                           */
6 /*    Copyright (C) 2002-2021 Konrad-Zuse-Zentrum                            */
7 /*                            fuer Informationstechnik Berlin                */
8 /*                                                                           */
9 /*  BMS 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 BMS; see the file COPYING. If not email to scip@zib.de.       */
13 /*                                                                           */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file   memory.h
17  * @brief  memory allocation routines
18  * @author Tobias Achterberg
19  * @author Gerald Gamrath
20  * @author Marc Pfetsch
21  */
22 
23 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
24 
25 #ifndef __BMS_MEMORY_H__
26 #define __BMS_MEMORY_H__
27 
28 #include <limits.h>
29 #include <stdlib.h>
30 #include <stddef.h>
31 
32 /*
33  * include build configuration flags
34  */
35 #ifndef NO_CONFIG_HEADER
36 #include "scip/config.h"
37 #include "scip/scip_export.h"
38 #endif
39 
40 #ifdef __cplusplus
41 
42 
43 /* special thanks to Daniel Junglas for following template and macros */
44 
45 template<typename T> T* docast(T*, void *v);
docast(T *,void * v)46 template<typename T> T* docast(T*, void *v) { return reinterpret_cast<T*>(v); }
47 
48 /* For C++11, we can easily check whether the types for memory functions like BMSduplicateXYZArray() are equal. */
49 #if __cplusplus > 199711L
50 #include <type_traits>
51 
52 /* the following adds a type check for the parameters, used in ASSIGNCHECK below */
docastcheck(T1 * v1,void * v,T2 * v2)53 template<typename T1, typename T2> T1* docastcheck(T1* v1, void* v, T2* v2)
54 {
55    typedef typename std::remove_const<T1>::type t1;
56    typedef typename std::remove_const<T2>::type t2;
57    static_assert(std::is_same<t1, t2>::value, "need equal types");
58    return reinterpret_cast<T1*>(v);
59 }
60 #else
61 /* for older compilers do nothing */
docastcheck(T1 * v1,void * v,T2 * v2)62 template<typename T1, typename T2> T1* docastcheck(T1* v1, void* v, T2* v2) { return reinterpret_cast<T1*>(v); }
63 #endif
64 
65 
66 extern "C" {
67 
68 #define ASSIGN(pointerstarstar, voidstarfunction) (*(pointerstarstar) = docast(*(pointerstarstar), (voidstarfunction)))
69 #define ASSIGNCHECK(pointerstarstar, voidstarfunction, origpointer) (*(pointerstarstar) = docastcheck(*(pointerstarstar), (voidstarfunction), (origpointer)))
70 
71 #else
72 
73 #define ASSIGN(pointerstarstar, voidstarfunction) (*(pointerstarstar) = (voidstarfunction))
74 #define ASSIGNCHECK(pointerstarstar, voidstarfunction, origpointer) (*(pointerstarstar) = (voidstarfunction))
75 
76 #endif
77 
78 /*
79  * Define the macro SCIP_EXPORT depending if the OS is Windows or not
80  */
81 #ifndef SCIP_EXPORT
82 
83 #if defined(_WIN32) || defined(_WIN64)
84 #define SCIP_EXPORT __declspec(dllexport)
85 #elif defined(__GNUC__) && __GNUC__ >= 4
86 #define SCIP_EXPORT __attribute__((__visibility__("default")))
87 #else
88 #define SCIP_EXPORT
89 #endif
90 
91 #endif
92 
93 /* define if not already existing to make file independent from def.h */
94 #ifndef SCIP_UNUSED
95 #define SCIP_UNUSED(x) ((void) (x))
96 #endif
97 
98 
99 /*************************************************************************************
100  * Standard Memory Management
101  *
102  * In debug mode, these methods extend malloc() and free() by logging all currently
103  * allocated memory elements in an allocation list. This can be used as a simple leak
104  * detection.
105  *************************************************************************************/
106 
107 /* Note: values that are passed as a size_t parameter are first converted to ptrdiff_t to be sure that negative numbers
108  * are extended to the larger size. Then they are converted to size_t. Thus, negative numbers are converted to very
109  * large size_t values. This is then checked within the functions. */
110 
111 #define BMSallocMemory(ptr)                   ASSIGN((ptr), BMSallocMemory_call( sizeof(**(ptr)), __FILE__, __LINE__ ))
112 #define BMSallocMemorySize(ptr,size)          ASSIGN((ptr), BMSallocMemory_call( (size_t)(ptrdiff_t)(size), __FILE__, __LINE__ ))
113 #define BMSallocMemoryCPP(size)               BMSallocMemory_call( (size_t)(ptrdiff_t)(size), __FILE__, __LINE__ )
114 #define BMSallocClearMemorySize(ptr,size)     ASSIGN((ptr), BMSallocClearMemory_call((size_t)(1), (size_t)(ptrdiff_t)(size), __FILE__, __LINE__ ))
115 #define BMSallocMemoryArray(ptr,num)          ASSIGN((ptr), BMSallocMemoryArray_call((size_t)(ptrdiff_t)(num), sizeof(**(ptr)), __FILE__, __LINE__ ))
116 #define BMSallocMemoryArrayCPP(num,size)      BMSallocMemoryArray_call( (size_t)(ptrdiff_t)(num), (size_t)(ptrdiff_t)(size), __FILE__, __LINE__ )
117 #define BMSallocClearMemoryArray(ptr,num)     ASSIGN((ptr), BMSallocClearMemory_call((size_t)(ptrdiff_t)(num), sizeof(**(ptr)), __FILE__, __LINE__ ))
118 #define BMSreallocMemorySize(ptr,size)        ASSIGN((ptr), BMSreallocMemory_call((void*)(*(ptr)), (size_t)(ptrdiff_t)(size), __FILE__, __LINE__ ))
119 #define BMSreallocMemoryArray(ptr,num)        ASSIGN((ptr), BMSreallocMemoryArray_call( *(ptr), (size_t)(ptrdiff_t)(num), sizeof(**(ptr)), __FILE__, __LINE__ ))
120 
121 #define BMSclearMemory(ptr)                   BMSclearMemory_call( (void*)(ptr), sizeof(*(ptr)) )
122 #define BMSclearMemoryArray(ptr, num)         BMSclearMemory_call( (void*)(ptr), (size_t)(ptrdiff_t)(num)*sizeof(*(ptr)) )
123 #define BMSclearMemorySize(ptr, size)         BMSclearMemory_call( (void*)(ptr), (size_t)(ptrdiff_t)(size) )
124 
125 #define BMScopyMemory(ptr, source)            BMScopyMemory_call( (void*)(ptr), (const void*)(source), sizeof(*(ptr)) )
126 #define BMScopyMemoryArray(ptr, source, num)  BMScopyMemory_call( (void*)(ptr), (const void*)(source), (size_t)(ptrdiff_t)(num)*sizeof(*(ptr)) )
127 #define BMScopyMemorySize(ptr, source, size)  BMScopyMemory_call( (void*)(ptr), (const void*)(source), (size_t)(ptrdiff_t)(size) )
128 
129 #define BMSmoveMemory(ptr, source)            BMSmoveMemory_call( (void*)(ptr), (const void*)(source), sizeof(*(ptr)) )
130 #define BMSmoveMemoryArray(ptr, source, num)  BMSmoveMemory_call( (void*)(ptr), (const void*)(source), (size_t)(ptrdiff_t)(num) * sizeof(*(ptr)) )
131 #define BMSmoveMemorySize(ptr, source, size)  BMSmoveMemory_call( (void*)(ptr), (const void*)(source), (size_t)(ptrdiff_t)(size) )
132 
133 #define BMSduplicateMemory(ptr, source)       ASSIGN((ptr), BMSduplicateMemory_call( (const void*)(source), sizeof(**(ptr)), __FILE__, __LINE__ ))
134 #define BMSduplicateMemorySize(ptr, source, size) ASSIGN((ptr), BMSduplicateMemory_call( (const void*)(source), (size_t)(ptrdiff_t)(size), __FILE__, __LINE__ ))
135 #define BMSduplicateMemoryArray(ptr, source, num) ASSIGNCHECK((ptr), BMSduplicateMemoryArray_call( (const void*)(source), (size_t)(ptrdiff_t)(num), \
136                                                   sizeof(**(ptr)), __FILE__, __LINE__ ), source)
137 #define BMSfreeMemory(ptr)                    BMSfreeMemory_call( (void**)(ptr), __FILE__, __LINE__ )
138 #define BMSfreeMemoryNull(ptr)                BMSfreeMemoryNull_call( (void**)(ptr), __FILE__, __LINE__ )
139 #define BMSfreeMemoryArray(ptr)               BMSfreeMemory_call( (void**)(ptr), __FILE__, __LINE__ )
140 #define BMSfreeMemoryArrayNull(ptr)           BMSfreeMemoryNull_call( (void**)(ptr), __FILE__, __LINE__ )
141 #define BMSfreeMemorySize(ptr)                BMSfreeMemory_call( (void**)(ptr), __FILE__, __LINE__ )
142 #define BMSfreeMemorySizeNull(ptr)            BMSfreeMemoryNull_call( (void**)(ptr), __FILE__, __LINE__ )
143 
144 #ifndef NDEBUG
145 #define BMSgetPointerSize(ptr)                BMSgetPointerSize_call(ptr)
146 #define BMSdisplayMemory()                    BMSdisplayMemory_call()
147 #define BMScheckEmptyMemory()                 BMScheckEmptyMemory_call()
148 #define BMSgetMemoryUsed()                    BMSgetMemoryUsed_call()
149 #else
150 #define BMSgetPointerSize(ptr)                0
151 #define BMSdisplayMemory()                    /**/
152 #define BMScheckEmptyMemory()                 /**/
153 #define BMSgetMemoryUsed()                    0LL
154 #endif
155 
156 /** allocates array and initializes it with 0; returns NULL if memory allocation failed */
157 SCIP_EXPORT
158 void* BMSallocClearMemory_call(
159    size_t                num,                /**< number of memory element to allocate */
160    size_t                typesize,           /**< size of memory element to allocate */
161    const char*           filename,           /**< source file where the allocation is performed */
162    int                   line                /**< line number in source file where the allocation is performed */
163    );
164 
165 /** allocates memory; returns NULL if memory allocation failed */
166 SCIP_EXPORT
167 void* BMSallocMemory_call(
168    size_t                size,               /**< size of memory element to allocate */
169    const char*           filename,           /**< source file where the allocation is performed */
170    int                   line                /**< line number in source file where the allocation is performed */
171    );
172 
173 /** allocates array; returns NULL if memory allocation failed */
174 SCIP_EXPORT
175 void* BMSallocMemoryArray_call(
176    size_t                num,                /**< number of components of array to allocate */
177    size_t                typesize,           /**< size of each component */
178    const char*           filename,           /**< source file where the allocation is performed */
179    int                   line                /**< line number in source file where the allocation is performed */
180    );
181 
182 /** allocates memory; returns NULL if memory allocation failed */
183 SCIP_EXPORT
184 void* BMSreallocMemory_call(
185    void*                 ptr,                /**< pointer to memory to reallocate */
186    size_t                size,               /**< new size of memory element */
187    const char*           filename,           /**< source file where the reallocation is performed */
188    int                   line                /**< line number in source file where the reallocation is performed */
189    );
190 
191 /** reallocates array; returns NULL if memory allocation failed */
192 SCIP_EXPORT
193 void* BMSreallocMemoryArray_call(
194    void*                 ptr,                /**< pointer to memory to reallocate */
195    size_t                num,                /**< number of components of array to allocate */
196    size_t                typesize,           /**< size of each component */
197    const char*           filename,           /**< source file where the reallocation is performed */
198    int                   line                /**< line number in source file where the reallocation is performed */
199    );
200 
201 /** clears a memory element (i.e. fills it with zeros) */
202 SCIP_EXPORT
203 void BMSclearMemory_call(
204    void*                 ptr,                /**< pointer to memory element */
205    size_t                size                /**< size of memory element */
206    );
207 
208 /** copies the contents of one memory element into another memory element */
209 SCIP_EXPORT
210 void BMScopyMemory_call(
211    void*                 ptr,                /**< pointer to target memory element */
212    const void*           source,             /**< pointer to source memory element */
213    size_t                size                /**< size of memory element to copy */
214    );
215 
216 /** moves the contents of one memory element into another memory element, should be used if both elements overlap,
217  *  otherwise BMScopyMemory is faster
218  */
219 SCIP_EXPORT
220 void BMSmoveMemory_call(
221    void*                 ptr,                /**< pointer to target memory element */
222    const void*           source,             /**< pointer to source memory element */
223    size_t                size                /**< size of memory element to copy */
224    );
225 
226 /** allocates memory and copies the contents of the given memory element into the new memory element */
227 SCIP_EXPORT
228 void* BMSduplicateMemory_call(
229    const void*           source,             /**< pointer to source memory element */
230    size_t                size,               /**< size of memory element to copy */
231    const char*           filename,           /**< source file where the duplication is performed */
232    int                   line                /**< line number in source file where the duplication is performed */
233    );
234 
235 /** allocates array and copies the contents of the given source array into the new array */
236 SCIP_EXPORT
237 void* BMSduplicateMemoryArray_call(
238    const void*           source,             /**< pointer to source memory element */
239    size_t                num,                /**< number of components of array to allocate */
240    size_t                typesize,           /**< size of each component */
241    const char*           filename,           /**< source file where the duplication is performed */
242    int                   line                /**< line number in source file where the duplication is performed */
243    );
244 
245 /** frees an allocated memory element and sets pointer to NULL */
246 SCIP_EXPORT
247 void BMSfreeMemory_call(
248    void**                ptr,                /**< pointer to pointer to memory element */
249    const char*           filename,           /**< source file where the deallocation is performed */
250    int                   line                /**< line number in source file where the deallocation is performed */
251    );
252 
253 /** frees an allocated memory element if pointer is not NULL and sets pointer to NULL */
254 SCIP_EXPORT
255 void BMSfreeMemoryNull_call(
256    void**                ptr,                /**< pointer to pointer to memory element */
257    const char*           filename,           /**< source file where the deallocation is performed */
258    int                   line                /**< line number in source file where the deallocation is performed */
259    );
260 
261 /** returns the size of an allocated memory element */
262 SCIP_EXPORT
263 size_t BMSgetPointerSize_call(
264    const void*           ptr                 /**< pointer to allocated memory */
265    );
266 
267 /** outputs information about currently allocated memory to the screen */
268 SCIP_EXPORT
269 void BMSdisplayMemory_call(
270    void
271    );
272 
273 /** displays a warning message on the screen, if allocated memory exists */
274 SCIP_EXPORT
275 void BMScheckEmptyMemory_call(
276    void
277    );
278 
279 /** returns total number of allocated bytes */
280 SCIP_EXPORT
281 long long BMSgetMemoryUsed_call(
282    void
283    );
284 
285 
286 
287 
288 /********************************************************************
289  * Chunk Memory Management
290  *
291  * Efficient memory management for multiple objects of the same size
292  ********************************************************************/
293 
294 typedef struct BMS_ChkMem BMS_CHKMEM;           /**< collection of memory chunks of the same element size */
295 
296 
297 #ifndef BMS_NOBLOCKMEM
298 
299 #define BMScreateChunkMemory(sz,isz,gbf)      BMScreateChunkMemory_call( (sz), (isz), (gbf), __FILE__, __LINE__ )
300 #define BMSclearChunkMemory(mem)              BMSclearChunkMemory_call( (mem), __FILE__, __LINE__ )
301 #define BMSdestroyChunkMemory(mem)            BMSdestroyChunkMemory_call( (mem), __FILE__, __LINE__ )
302 
303 #define BMSallocChunkMemory(mem,ptr)          ASSIGN((ptr), BMSallocChunkMemory_call((mem), sizeof(**(ptr)), __FILE__, __LINE__))
304 #define BMSduplicateChunkMemory(mem, ptr, source) ASSIGN((ptr), BMSduplicateChunkMemory_call((mem), (const void*)(source), \
305                                                 sizeof(**(ptr)), __FILE__, __LINE__ ))
306 #define BMSfreeChunkMemory(mem,ptr)           BMSfreeChunkMemory_call( (mem), (void**)(ptr), sizeof(**(ptr)), __FILE__, __LINE__ )
307 #define BMSfreeChunkMemoryNull(mem,ptr)       BMSfreeChunkMemoryNull_call( (mem), (void**)(ptr), sizeof(**(ptr)), __FILE__, __LINE__ )
308 #define BMSgarbagecollectChunkMemory(mem)     BMSgarbagecollectChunkMemory_call(mem)
309 #define BMSgetChunkMemoryUsed(mem)            BMSgetChunkMemoryUsed_call(mem)
310 
311 #else
312 
313 /* block memory management mapped to standard memory management */
314 
315 #define BMScreateChunkMemory(sz,isz,gbf)           (void*)(0x01) /* dummy to not return a NULL pointer */
316 #define BMSclearChunkMemory(mem)                   /**/
317 #define BMSclearChunkMemoryNull(mem)               /**/
318 #define BMSdestroyChunkMemory(mem)                 /**/
319 #define BMSdestroyChunkMemoryNull(mem)             /**/
320 #define BMSallocChunkMemory(mem,ptr)               BMSallocMemory(ptr)
321 #define BMSduplicateChunkMemory(mem, ptr, source)  BMSduplicateMemory(ptr,source)
322 #define BMSfreeChunkMemory(mem,ptr)                BMSfreeMemory(ptr)
323 #define BMSfreeChunkMemoryNull(mem,ptr)            BMSfreeMemoryNull(ptr)
324 #define BMSgarbagecollectChunkMemory(mem)          /**/
325 #define BMSgetChunkMemoryUsed(mem)                 0LL
326 
327 #endif
328 
329 
330 /** aligns the given byte size corresponding to the minimal alignment for chunk and block memory */
331 SCIP_EXPORT
332 void BMSalignMemsize(
333    size_t*               size                /**< pointer to the size to align */
334    );
335 
336 /** checks whether the given size meets the alignment conditions for chunk and block memory  */
337 SCIP_EXPORT
338 int BMSisAligned(
339    size_t                size                /**< size to check for alignment */
340    );
341 
342 /** creates a new chunk block data structure */
343 SCIP_EXPORT
344 BMS_CHKMEM* BMScreateChunkMemory_call(
345    size_t                size,               /**< element size of the chunk block */
346    int                   initchunksize,      /**< number of elements in the first chunk of the chunk block */
347    int                   garbagefactor,      /**< garbage collector is called, if at least garbagefactor * avg. chunksize
348                                               *   elements are free (-1: disable garbage collection) */
349    const char*           filename,           /**< source file of the function call */
350    int                   line                /**< line number in source file of the function call */
351    );
352 
353 /** clears a chunk block data structure */
354 SCIP_EXPORT
355 void BMSclearChunkMemory_call(
356    BMS_CHKMEM*           chkmem,             /**< chunk block */
357    const char*           filename,           /**< source file of the function call */
358    int                   line                /**< line number in source file of the function call */
359    );
360 
361 /** destroys and frees a chunk block data structure */
362 SCIP_EXPORT
363 void BMSdestroyChunkMemory_call(
364    BMS_CHKMEM**          chkmem,             /**< pointer to chunk block */
365    const char*           filename,           /**< source file of the function call */
366    int                   line                /**< line number in source file of the function call */
367    );
368 
369 /** allocates a memory element of the given chunk block */
370 SCIP_EXPORT
371 void* BMSallocChunkMemory_call(
372    BMS_CHKMEM*           chkmem,             /**< chunk block */
373    size_t                size,               /**< size of memory element to allocate (only needed for sanity check) */
374    const char*           filename,           /**< source file of the function call */
375    int                   line                /**< line number in source file of the function call */
376    );
377 
378 /** duplicates a given memory element by allocating a new element of the same chunk block and copying the data */
379 SCIP_EXPORT
380 void* BMSduplicateChunkMemory_call(
381    BMS_CHKMEM*           chkmem,             /**< chunk block */
382    const void*           source,             /**< source memory element */
383    size_t                size,               /**< size of memory element to allocate (only needed for sanity check) */
384    const char*           filename,           /**< source file of the function call */
385    int                   line                /**< line number in source file of the function call */
386    );
387 
388 /** frees a memory element of the given chunk block and sets pointer to NULL */
389 SCIP_EXPORT
390 void BMSfreeChunkMemory_call(
391    BMS_CHKMEM*           chkmem,             /**< chunk block */
392    void**                ptr,                /**< pointer to pointer to memory element to free */
393    size_t                size,               /**< size of memory element to allocate (only needed for sanity check) */
394    const char*           filename,           /**< source file of the function call */
395    int                   line                /**< line number in source file of the function call */
396    );
397 
398 /** frees a memory element of the given chunk block if pointer is not NULL and sets pointer to NULL */
399 SCIP_EXPORT
400 void BMSfreeChunkMemoryNull_call(
401    BMS_CHKMEM*           chkmem,             /**< chunk block */
402    void**                ptr,                /**< pointer to pointer to memory element to free */
403    size_t                size,               /**< size of memory element to allocate (only needed for sanity check) */
404    const char*           filename,           /**< source file of the function call */
405    int                   line                /**< line number in source file of the function call */
406    );
407 
408 /** calls garbage collection of chunk block and frees chunks without allocated memory elements */
409 SCIP_EXPORT
410 void BMSgarbagecollectChunkMemory_call(
411    BMS_CHKMEM*           chkmem              /**< chunk block */
412    );
413 
414 /** returns the number of allocated bytes in the chunk block */
415 SCIP_EXPORT
416 long long BMSgetChunkMemoryUsed_call(
417    const BMS_CHKMEM*     chkmem              /**< chunk block */
418    );
419 
420 
421 
422 
423 /***********************************************************
424  * Block Memory Management
425  *
426  * Efficient memory management for objects of varying sizes
427  ***********************************************************/
428 
429 typedef struct BMS_BlkMem BMS_BLKMEM;           /**< block memory: collection of chunk blocks */
430 
431 #ifndef BMS_NOBLOCKMEM
432 
433 /* block memory methods for faster memory access */
434 
435 /* Note: values that are passed as a size_t parameter are first converted to ptrdiff_t to be sure that negative numbers
436  * are extended to the larger size. Then they are converted to size_t. Thus, negative numbers are converted to very
437  * large size_t values. This is then checked within the functions. */
438 
439 #define BMScreateBlockMemory(csz,gbf)         BMScreateBlockMemory_call( (csz), (gbf), __FILE__, __LINE__ )
440 #define BMSclearBlockMemory(mem)              BMSclearBlockMemory_call( (mem), __FILE__, __LINE__ )
441 #define BMSdestroyBlockMemory(mem)            BMSdestroyBlockMemory_call( (mem), __FILE__, __LINE__ )
442 
443 #define BMSallocBlockMemory(mem,ptr)          ASSIGN((ptr), BMSallocBlockMemory_call((mem), sizeof(**(ptr)), __FILE__, __LINE__))
444 #define BMSallocBlockMemorySize(mem,ptr,size) ASSIGN((ptr), BMSallocBlockMemory_call((mem), (size_t)(ptrdiff_t)(size), __FILE__, __LINE__))
445 #define BMSallocBlockMemoryArray(mem,ptr,num) ASSIGN((ptr), BMSallocBlockMemoryArray_call((mem), (size_t)(ptrdiff_t)(num), sizeof(**(ptr)), __FILE__, __LINE__))
446 #define BMSallocClearBlockMemoryArray(mem,ptr,num) ASSIGN((ptr), BMSallocClearBlockMemoryArray_call((mem), (size_t)(ptrdiff_t)(num), sizeof(**(ptr)), __FILE__, __LINE__))
447 #define BMSreallocBlockMemorySize(mem,ptr,oldsize,newsize) ASSIGN((ptr), BMSreallocBlockMemory_call((mem), (void*)(*(ptr)), \
448                                                 (size_t)(ptrdiff_t)(oldsize), (size_t)(ptrdiff_t)(newsize), __FILE__, __LINE__))
449 #define BMSreallocBlockMemoryArray(mem,ptr,oldnum,newnum) ASSIGN((ptr), BMSreallocBlockMemoryArray_call((mem), (void*)(*(ptr)), \
450                                                 (size_t)(ptrdiff_t)(oldnum), (size_t)(ptrdiff_t)(newnum), sizeof(**(ptr)), __FILE__, __LINE__))
451 #define BMSduplicateBlockMemory(mem, ptr, source) ASSIGN((ptr), BMSduplicateBlockMemory_call((mem), (const void*)(source), \
452                                                 sizeof(**(ptr)), __FILE__, __LINE__ ))
453 #define BMSduplicateBlockMemoryArray(mem, ptr, source, num) ASSIGNCHECK((ptr), BMSduplicateBlockMemoryArray_call( (mem), (const void*)(source), \
454                                                 (size_t)(ptrdiff_t)(num), sizeof(**(ptr)), __FILE__, __LINE__ ), source)
455 
456 #define BMSfreeBlockMemory(mem,ptr)           BMSfreeBlockMemory_call( (mem), (void**)(ptr), sizeof(**(ptr)), __FILE__, __LINE__ )
457 #define BMSfreeBlockMemoryNull(mem,ptr)       BMSfreeBlockMemoryNull_call( (mem), (void**)(ptr), sizeof(**(ptr)), __FILE__, __LINE__ )
458 #define BMSfreeBlockMemoryArray(mem,ptr,num)  BMSfreeBlockMemory_call( (mem), (void**)(ptr), (num)*sizeof(**(ptr)), __FILE__, __LINE__ )
459 #define BMSfreeBlockMemoryArrayNull(mem,ptr,num) BMSfreeBlockMemoryNull_call( (mem), (void**)(ptr), (num)*sizeof(**(ptr)), __FILE__, __LINE__ )
460 #define BMSfreeBlockMemorySize(mem,ptr,size)  BMSfreeBlockMemory_call( (mem), (void**)(ptr), (size_t)(ptrdiff_t)(size), __FILE__, __LINE__ )
461 #define BMSfreeBlockMemorySizeNull(mem,ptr,size) BMSfreeBlockMemory_call( (mem), (void**)(ptr), (size_t)(ptrdiff_t)(size), __FILE__, __LINE__ )
462 
463 #define BMSgarbagecollectBlockMemory(mem)     BMSgarbagecollectBlockMemory_call(mem)
464 #define BMSgetBlockMemoryAllocated(mem)       BMSgetBlockMemoryAllocated_call(mem)
465 #define BMSgetBlockMemoryUsed(mem)            BMSgetBlockMemoryUsed_call(mem)
466 #define BMSgetBlockMemoryUnused(mem)          BMSgetBlockMemoryUnused_call(mem)
467 #define BMSgetBlockMemoryUsedMax(mem)         BMSgetBlockMemoryUsedMax_call(mem)
468 #define BMSgetBlockMemoryUnusedMax(mem)       BMSgetBlockMemoryUnusedMax_call(mem)
469 #define BMSgetBlockMemoryAllocatedMax(mem)    BMSgetBlockMemoryAllocatedMax_call(mem)
470 #define BMSgetBlockPointerSize(mem,ptr)       BMSgetBlockPointerSize_call((mem), (ptr))
471 #define BMSdisplayBlockMemory(mem)            BMSdisplayBlockMemory_call(mem)
472 #define BMSblockMemoryCheckEmpty(mem)         BMScheckEmptyBlockMemory_call(mem)
473 
474 #else
475 
476 /* block memory management mapped to standard memory management */
477 
478 #define BMScreateBlockMemory(csz,gbf)                        (SCIP_UNUSED(csz), SCIP_UNUSED(gbf), (void*)(0x01)) /* dummy to not return a NULL pointer */
479 #define BMSclearBlockMemory(mem)                             SCIP_UNUSED(mem)
480 #define BMSclearBlockMemoryNull(mem)                         SCIP_UNUSED(mem)
481 #define BMSdestroyBlockMemory(mem)                           SCIP_UNUSED(mem)
482 #define BMSdestroyBlockMemoryNull(mem)                       SCIP_UNUSED(mem)
483 #define BMSallocBlockMemory(mem,ptr)                         (SCIP_UNUSED(mem), BMSallocMemory(ptr))
484 #define BMSallocBlockMemoryArray(mem,ptr,num)                (SCIP_UNUSED(mem), BMSallocMemoryArray(ptr,num))
485 #define BMSallocClearBlockMemoryArray(mem,ptr,num)           (SCIP_UNUSED(mem), BMSallocClearMemoryArray(ptr,num))
486 #define BMSallocBlockMemorySize(mem,ptr,size)                (SCIP_UNUSED(mem), BMSallocMemorySize(ptr,size))
487 #define BMSreallocBlockMemoryArray(mem,ptr,oldnum,newnum)    (SCIP_UNUSED(mem), SCIP_UNUSED(oldnum), BMSreallocMemoryArray(ptr,newnum))
488 #define BMSreallocBlockMemorySize(mem,ptr,oldsize,newsize)   (SCIP_UNUSED(mem), SCIP_UNUSED(oldsize), BMSreallocMemorySize(ptr,newsize))
489 #define BMSduplicateBlockMemory(mem, ptr, source)            (SCIP_UNUSED(mem), BMSduplicateMemory(ptr,source))
490 #define BMSduplicateBlockMemoryArray(mem, ptr, source, num)  (SCIP_UNUSED(mem), BMSduplicateMemoryArray(ptr,source,num))
491 #define BMSfreeBlockMemory(mem,ptr)                          (SCIP_UNUSED(mem), BMSfreeMemory(ptr))
492 #define BMSfreeBlockMemoryNull(mem,ptr)                      (SCIP_UNUSED(mem), BMSfreeMemoryNull(ptr))
493 #define BMSfreeBlockMemoryArray(mem,ptr,num)                 (SCIP_UNUSED(mem), SCIP_UNUSED(num), BMSfreeMemoryArray(ptr))
494 #define BMSfreeBlockMemoryArrayNull(mem,ptr,num)             (SCIP_UNUSED(mem), SCIP_UNUSED(num), BMSfreeMemoryArrayNull(ptr))
495 #define BMSfreeBlockMemorySize(mem,ptr,size)                 (SCIP_UNUSED(mem), SCIP_UNUSED(size), BMSfreeMemory(ptr))
496 #define BMSfreeBlockMemorySizeNull(mem,ptr,size)             (SCIP_UNUSED(mem), SCIP_UNUSED(size), BMSfreeMemoryNull(ptr))
497 #define BMSgarbagecollectBlockMemory(mem)                    SCIP_UNUSED(mem)
498 #define BMSgetBlockMemoryAllocated(mem)                      (SCIP_UNUSED(mem), 0LL)
499 #define BMSgetBlockMemoryUsed(mem)                           (SCIP_UNUSED(mem), 0LL)
500 #define BMSgetBlockMemoryUnused(mem)                         (SCIP_UNUSED(mem), 0LL)
501 #define BMSgetBlockMemoryUsedMax(mem)                        (SCIP_UNUSED(mem), 0LL)
502 #define BMSgetBlockMemoryUnusedMax(mem)                      (SCIP_UNUSED(mem), 0LL)
503 #define BMSgetBlockMemoryAllocatedMax(mem)                   (SCIP_UNUSED(mem), 0LL)
504 #define BMSgetBlockPointerSize(mem,ptr)                      (SCIP_UNUSED(mem), SCIP_UNUSED(ptr), 0)
505 #define BMSdisplayBlockMemory(mem)                           SCIP_UNUSED(mem)
506 #define BMSblockMemoryCheckEmpty(mem)                        (SCIP_UNUSED(mem), 0LL)
507 
508 #endif
509 
510 
511 /** creates a block memory allocation data structure */
512 SCIP_EXPORT
513 BMS_BLKMEM* BMScreateBlockMemory_call(
514    int                   initchunksize,      /**< number of elements in the first chunk of each chunk block */
515    int                   garbagefactor,      /**< garbage collector is called, if at least garbagefactor * avg. chunksize
516                                               *   elements are free (-1: disable garbage collection) */
517    const char*           filename,           /**< source file of the function call */
518    int                   line                /**< line number in source file of the function call */
519    );
520 
521 /** frees all chunk blocks in the block memory */
522 SCIP_EXPORT
523 void BMSclearBlockMemory_call(
524    BMS_BLKMEM*           blkmem,             /**< block memory */
525    const char*           filename,           /**< source file of the function call */
526    int                   line                /**< line number in source file of the function call */
527    );
528 
529 /** clears and deletes block memory */
530 SCIP_EXPORT
531 void BMSdestroyBlockMemory_call(
532    BMS_BLKMEM**          blkmem,             /**< pointer to block memory */
533    const char*           filename,           /**< source file of the function call */
534    int                   line                /**< line number in source file of the function call */
535    );
536 
537 /** allocates memory in the block memory pool */
538 SCIP_EXPORT
539 void* BMSallocBlockMemory_call(
540    BMS_BLKMEM*           blkmem,             /**< block memory */
541    size_t                size,               /**< size of memory element to allocate */
542    const char*           filename,           /**< source file of the function call */
543    int                   line                /**< line number in source file of the function call */
544    );
545 
546 /** allocates array in the block memory pool */
547 SCIP_EXPORT
548 void* BMSallocBlockMemoryArray_call(
549    BMS_BLKMEM*           blkmem,             /**< block memory */
550    size_t                num,                /**< size of array to be allocated */
551    size_t                typesize,           /**< size of each component */
552    const char*           filename,           /**< source file of the function call */
553    int                   line                /**< line number in source file of the function call */
554    );
555 
556 /** allocates array in the block memory pool and clears it */
557 SCIP_EXPORT
558 void* BMSallocClearBlockMemoryArray_call(
559    BMS_BLKMEM*           blkmem,             /**< block memory */
560    size_t                num,                /**< size of array to be allocated */
561    size_t                typesize,           /**< size of each component */
562    const char*           filename,           /**< source file of the function call */
563    int                   line                /**< line number in source file of the function call */
564    );
565 
566 /** resizes memory element in the block memory pool and copies the data */
567 SCIP_EXPORT
568 void* BMSreallocBlockMemory_call(
569    BMS_BLKMEM*           blkmem,             /**< block memory */
570    void*                 ptr,                /**< memory element to reallocated */
571    size_t                oldsize,            /**< old size of memory element */
572    size_t                newsize,            /**< new size of memory element */
573    const char*           filename,           /**< source file of the function call */
574    int                   line                /**< line number in source file of the function call */
575    );
576 
577 /** resizes array in the block memory pool and copies the data */
578 SCIP_EXPORT
579 void* BMSreallocBlockMemoryArray_call(
580    BMS_BLKMEM*           blkmem,             /**< block memory */
581    void*                 ptr,                /**< memory element to reallocated */
582    size_t                oldnum,             /**< old size of array */
583    size_t                newnum,             /**< new size of array */
584    size_t                typesize,           /**< size of each component */
585    const char*           filename,           /**< source file of the function call */
586    int                   line                /**< line number in source file of the function call */
587    );
588 
589 /** duplicates memory element in the block memory pool and copies the data */
590 SCIP_EXPORT
591 void* BMSduplicateBlockMemory_call(
592    BMS_BLKMEM*           blkmem,             /**< block memory */
593    const void*           source,             /**< memory element to duplicate */
594    size_t                size,               /**< size of memory elements */
595    const char*           filename,           /**< source file of the function call */
596    int                   line                /**< line number in source file of the function call */
597    );
598 
599 /** duplicates array in the block memory pool and copies the data */
600 SCIP_EXPORT
601 void* BMSduplicateBlockMemoryArray_call(
602    BMS_BLKMEM*           blkmem,             /**< block memory */
603    const void*           source,             /**< memory element to duplicate */
604    size_t                num,                /**< size of array to be duplicated */
605    size_t                typesize,           /**< size of each component */
606    const char*           filename,           /**< source file of the function call */
607    int                   line                /**< line number in source file of the function call */
608    );
609 
610 /** frees memory element in the block memory pool and sets pointer to NULL */
611 SCIP_EXPORT
612 void BMSfreeBlockMemory_call(
613    BMS_BLKMEM*           blkmem,             /**< block memory */
614    void**                ptr,                /**< pointer to pointer to memory element to free */
615    size_t                size,               /**< size of memory element */
616    const char*           filename,           /**< source file of the function call */
617    int                   line                /**< line number in source file of the function call */
618    );
619 
620 /** frees memory element in the block memory pool if pointer is not NULL and sets pointer to NULL */
621 SCIP_EXPORT
622 void BMSfreeBlockMemoryNull_call(
623    BMS_BLKMEM*           blkmem,             /**< block memory */
624    void**                ptr,                /**< pointer to pointer to memory element to free */
625    size_t                size,               /**< size of memory element */
626    const char*           filename,           /**< source file of the function call */
627    int                   line                /**< line number in source file of the function call */
628    );
629 
630 /** calls garbage collection of block memory, frees chunks without allocated memory elements, and frees
631  *  chunk blocks without any chunks
632  */
633 SCIP_EXPORT
634 void BMSgarbagecollectBlockMemory_call(
635    BMS_BLKMEM*           blkmem              /**< block memory */
636    );
637 
638 /** returns the number of allocated bytes in the block memory */
639 SCIP_EXPORT
640 long long BMSgetBlockMemoryAllocated_call(
641    const BMS_BLKMEM*     blkmem              /**< block memory */
642    );
643 
644 /** returns the number of used bytes in the block memory */
645 SCIP_EXPORT
646 long long BMSgetBlockMemoryUsed_call(
647    const BMS_BLKMEM*     blkmem              /**< block memory */
648    );
649 
650 /** returns the number of allocated but not used bytes in the block memory */
651 SCIP_EXPORT
652 long long BMSgetBlockMemoryUnused_call(
653    const BMS_BLKMEM*     blkmem              /**< block memory */
654    );
655 
656 /** returns the maximal number of used bytes in the block memory */
657 SCIP_EXPORT
658 long long BMSgetBlockMemoryUsedMax_call(
659    const BMS_BLKMEM*     blkmem              /**< block memory */
660    );
661 
662 /** returns the maximal number of allocated but not used bytes in the block memory */
663 SCIP_EXPORT
664 long long BMSgetBlockMemoryUnusedMax_call(
665    const BMS_BLKMEM*     blkmem              /**< block memory */
666    );
667 
668 /** returns the maximal number of allocated bytes in the block memory */
669 long long BMSgetBlockMemoryAllocatedMax_call(
670    const BMS_BLKMEM*     blkmem              /**< block memory */
671    );
672 
673 /** returns the size of the given memory element; returns 0, if the element is not member of the block memory */
674 SCIP_EXPORT
675 size_t BMSgetBlockPointerSize_call(
676    const BMS_BLKMEM*     blkmem,             /**< block memory */
677    const void*           ptr                 /**< memory element */
678    );
679 
680 /** outputs allocation diagnostics of block memory */
681 SCIP_EXPORT
682 void BMSdisplayBlockMemory_call(
683    const BMS_BLKMEM*     blkmem              /**< block memory */
684    );
685 
686 /** outputs error messages, if there are allocated elements in the block memory and returns number of unfreed bytes */
687 SCIP_EXPORT
688 long long BMScheckEmptyBlockMemory_call(
689    const BMS_BLKMEM*     blkmem              /**< block memory */
690    );
691 
692 
693 
694 
695 
696 /***********************************************************
697  * Buffer Memory Management
698  *
699  * Efficient memory management for temporary objects
700  ***********************************************************/
701 
702 typedef struct BMS_BufMem BMS_BUFMEM;        /**< buffer memory for temporary objects */
703 
704 /* Note: values that are passed as a size_t parameter are first converted to ptrdiff_t to be sure that negative numbers
705  * are extended to the larger size. Then they are converted to size_t. Thus, negative numbers are converted to very
706  * large size_t values. This is then checked within the functions. */
707 
708 #define BMSallocBufferMemory(mem,ptr)        ASSIGN((ptr), BMSallocBufferMemory_call((mem), sizeof(**(ptr)), __FILE__, __LINE__))
709 #define BMSallocBufferMemorySize(mem,ptr,size) ASSIGN((ptr), BMSallocBufferMemory_call((mem), (size_t)(ptrdiff_t)(size), __FILE__, __LINE__))
710 #define BMSreallocBufferMemorySize(mem,ptr,size) \
711                                              ASSIGN((ptr), BMSreallocBufferMemory_call((mem), (void*)(*(ptr)), (size_t)(ptrdiff_t)(size), __FILE__, __LINE__))
712 #define BMSallocBufferMemoryArray(mem,ptr,num) ASSIGN((ptr), BMSallocBufferMemoryArray_call((mem), (size_t)(ptrdiff_t)(num), sizeof(**(ptr)), __FILE__, __LINE__))
713 #define BMSallocClearBufferMemoryArray(mem,ptr,num) ASSIGN((ptr), BMSallocClearBufferMemoryArray_call((mem), (size_t)(ptrdiff_t)(num), sizeof(**(ptr)), __FILE__, __LINE__))
714 #define BMSreallocBufferMemoryArray(mem,ptr,num) ASSIGN((ptr), BMSreallocBufferMemoryArray_call((mem), (void*)(*(ptr)), (size_t)(ptrdiff_t)(num), \
715                                                  sizeof(**(ptr)), __FILE__, __LINE__))
716 #define BMSduplicateBufferMemory(mem,ptr,source,size) \
717                                              ASSIGN((ptr), BMSduplicateBufferMemory_call((mem), (const void*)(source), (size_t)(ptrdiff_t)(size), __FILE__, __LINE__))
718 #define BMSduplicateBufferMemoryArray(mem,ptr,source,num) ASSIGNCHECK((ptr), BMSduplicateBufferMemoryArray_call((mem), \
719                                                  (const void*)(source), (size_t)(ptrdiff_t)(num), sizeof(**(ptr)), __FILE__, __LINE__), source)
720 
721 #define BMSfreeBufferMemory(mem,ptr)         BMSfreeBufferMemory_call((mem), (void**)(ptr), __FILE__, __LINE__)
722 #define BMSfreeBufferMemoryNull(mem,ptr)     BMSfreeBufferMemoryNull_call((mem), (void**)(ptr), __FILE__, __LINE__)
723 #define BMSfreeBufferMemoryArray(mem,ptr)    BMSfreeBufferMemory_call((mem), (void**)(ptr), __FILE__, __LINE__)
724 #define BMSfreeBufferMemoryArrayNull(mem,ptr) BMSfreeBufferMemoryNull_call((mem), (void**)(ptr), __FILE__, __LINE__)
725 #define BMSfreeBufferMemorySize(mem,ptr)     BMSfreeBufferMemory_call((mem), (void**)(ptr), __FILE__, __LINE__);
726 #define BMSfreeBufferMemorySizeNull(mem,ptr) BMSfreeBufferMemoryNull_call((mem), (void**)(ptr), __FILE__, __LINE__)
727 
728 #define BMScreateBufferMemory(fac,init,clean) BMScreateBufferMemory_call((fac), (init), (clean), __FILE__, __LINE__)
729 #define BMSdestroyBufferMemory(mem)          BMSdestroyBufferMemory_call((mem), __FILE__, __LINE__)
730 
731 
732 /** creates memory buffer storage */
733 SCIP_EXPORT
734 BMS_BUFMEM* BMScreateBufferMemory_call(
735    double                arraygrowfac,       /**< memory growing factor for dynamically allocated arrays */
736    int                   arraygrowinit,      /**< initial size of dynamically allocated arrays */
737    unsigned int          clean,              /**< should the memory blocks in the buffer be initialized to zero? */
738    const char*           filename,           /**< source file of the function call */
739    int                   line                /**< line number in source file of the function call */
740    );
741 
742 /** destroys buffer memory */
743 SCIP_EXPORT
744 void BMSdestroyBufferMemory_call(
745    BMS_BUFMEM**          buffer,             /**< pointer to memory buffer storage */
746    const char*           filename,           /**< source file of the function call */
747    int                   line                /**< line number in source file of the function call */
748    );
749 
750 /** set arraygrowfac */
751 SCIP_EXPORT
752 void BMSsetBufferMemoryArraygrowfac(
753    BMS_BUFMEM*           buffer,             /**< pointer to memory buffer storage */
754    double                arraygrowfac        /**< memory growing factor for dynamically allocated arrays */
755    );
756 
757 /** set arraygrowinit */
758 SCIP_EXPORT
759 void BMSsetBufferMemoryArraygrowinit(
760    BMS_BUFMEM*           buffer,             /**< pointer to memory buffer storage */
761    int                   arraygrowinit       /**< initial size of dynamically allocated arrays */
762    );
763 
764 /** allocates the next unused buffer */
765 SCIP_EXPORT
766 void* BMSallocBufferMemory_call(
767    BMS_BUFMEM*           buffer,             /**< memory buffer storage */
768    size_t                size,               /**< minimal required size of the buffer */
769    const char*           filename,           /**< source file of the function call */
770    int                   line                /**< line number in source file of the function call */
771    );
772 
773 /** allocates the next unused buffer array */
774 SCIP_EXPORT
775 void* BMSallocBufferMemoryArray_call(
776    BMS_BUFMEM*           buffer,             /**< memory buffer storage */
777    size_t                num,                /**< size of array to be allocated */
778    size_t                typesize,           /**< size of components */
779    const char*           filename,           /**< source file of the function call */
780    int                   line                /**< line number in source file of the function call */
781    );
782 
783 /** allocates the next unused buffer and clears it */
784 SCIP_EXPORT
785 void* BMSallocClearBufferMemoryArray_call(
786    BMS_BUFMEM*           buffer,             /**< memory buffer storage */
787    size_t                num,                /**< size of array to be allocated */
788    size_t                typesize,           /**< size of components */
789    const char*           filename,           /**< source file of the function call */
790    int                   line                /**< line number in source file of the function call */
791    );
792 
793 /** reallocates the buffer to at least the given size */
794 SCIP_EXPORT
795 void* BMSreallocBufferMemory_call(
796    BMS_BUFMEM*           buffer,             /**< memory buffer storage */
797    void*                 ptr,                /**< pointer to the allocated memory buffer */
798    size_t                size,               /**< minimal required size of the buffer */
799    const char*           filename,           /**< source file of the function call */
800    int                   line                /**< line number in source file of the function call */
801    );
802 
803 /** reallocates an array in the buffer to at least the given size */
804 SCIP_EXPORT
805 void* BMSreallocBufferMemoryArray_call(
806    BMS_BUFMEM*           buffer,             /**< memory buffer storage */
807    void*                 ptr,                /**< pointer to the allocated memory buffer */
808    size_t                num,                /**< size of array to be allocated */
809    size_t                typesize,           /**< size of components */
810    const char*           filename,           /**< source file of the function call */
811    int                   line                /**< line number in source file of the function call */
812    );
813 
814 /** allocates the next unused buffer and copies the given memory into the buffer */
815 SCIP_EXPORT
816 void* BMSduplicateBufferMemory_call(
817    BMS_BUFMEM*           buffer,             /**< memory buffer storage */
818    const void*           source,             /**< memory block to copy into the buffer */
819    size_t                size,               /**< minimal required size of the buffer */
820    const char*           filename,           /**< source file of the function call */
821    int                   line                /**< line number in source file of the function call */
822    );
823 
824 /** allocates an array in the next unused buffer and copies the given memory into the buffer */
825 SCIP_EXPORT
826 void* BMSduplicateBufferMemoryArray_call(
827    BMS_BUFMEM*           buffer,             /**< memory buffer storage */
828    const void*           source,             /**< memory block to copy into the buffer */
829    size_t                num,                /**< size of array to be allocated */
830    size_t                typesize,           /**< size of components */
831    const char*           filename,           /**< source file of the function call */
832    int                   line                /**< line number in source file of the function call */
833    );
834 
835 /** frees a buffer and sets pointer to NULL */
836 SCIP_EXPORT
837 void BMSfreeBufferMemory_call(
838    BMS_BUFMEM*           buffer,             /**< memory buffer storage */
839    void**                ptr,                /**< pointer to pointer to the allocated memory buffer */
840    const char*           filename,           /**< source file of the function call */
841    int                   line                /**< line number in source file of the function call */
842    );
843 
844 /** frees a buffer if pointer is not NULL and sets pointer to NULL */
845 SCIP_EXPORT
846 void BMSfreeBufferMemoryNull_call(
847    BMS_BUFMEM*           buffer,             /**< memory buffer storage */
848    void**                ptr,                /**< pointer to pointer to the allocated memory buffer */
849    const char*           filename,           /**< source file of the function call */
850    int                   line                /**< line number in source file of the function call */
851    );
852 
853 /** gets number of used buffers */
854 SCIP_EXPORT
855 size_t BMSgetNUsedBufferMemory(
856    BMS_BUFMEM*           buffer              /**< memory buffer storage */
857    );
858 
859 /** returns the number of allocated bytes in the buffer memory */
860 SCIP_EXPORT
861 long long BMSgetBufferMemoryUsed(
862    const BMS_BUFMEM*     bufmem              /**< buffer memory */
863    );
864 
865 /** outputs statistics about currently allocated buffers to the screen */
866 SCIP_EXPORT
867 void BMSprintBufferMemory(
868    BMS_BUFMEM*           buffer              /**< memory buffer storage */
869    );
870 
871 
872 #ifdef __cplusplus
873 }
874 #endif
875 
876 #endif
877