this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Christian Schulte <schulte@gecode.org>
5 *
6 * Copyright:
7 * Christian Schulte, 2008
8 *
9 * This file is part of Gecode, the generic constraint
10 * development environment:
11 * http://www.gecode.org
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining
14 * a copy of this software and associated documentation files (the
15 * "Software"), to deal in the Software without restriction, including
16 * without limitation the rights to use, copy, modify, merge, publish,
17 * distribute, sublicense, and/or sell copies of the Software, and to
18 * permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be
22 * included in all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 *
32 */
33
34#include <cstring>
35#include <cstdlib>
36#include <algorithm>
37
38#ifdef GECODE_PEAKHEAP_MALLOC_H
39#include <malloc.h>
40#endif
41
42#ifdef GECODE_PEAKHEAP_MALLOC_MALLOC_H
43#include <malloc/malloc.h>
44#endif
45
46namespace Gecode {
47
48 /**
49 * \defgroup FuncMemHeap %Heap memory management
50 *
51 * \ingroup FuncMem
52 */
53
54
55 /**
56 * \brief %Heap memory management class
57 *
58 * All routines throw an exception of MemoryExhausted, if a request
59 * cannot be fulfilled.
60 * \ingroup FuncMemHeap
61 */
62 class Heap {
63 public:
64 /// Default constructor (ensuring that only a single instance is created)
65 Heap(void);
66 /// \name Typed allocation routines
67 //@{
68 /**
69 * \brief Allocate block of \a n objects of type \a T from heap
70 *
71 * Note that this function implements C++ semantics: the default
72 * constructor of \a T is run for all \a n objects.
73 */
74 template<class T>
75 T* alloc(long unsigned int n);
76 /**
77 * \brief Allocate block of \a n objects of type \a T from heap
78 *
79 * Note that this function implements C++ semantics: the default
80 * constructor of \a T is run for all \a n objects.
81 */
82 template<class T>
83 T* alloc(long int n);
84 /**
85 * \brief Allocate block of \a n objects of type \a T from heap
86 *
87 * Note that this function implements C++ semantics: the default
88 * constructor of \a T is run for all \a n objects.
89 */
90 template<class T>
91 T* alloc(unsigned int n);
92 /**
93 * \brief Allocate block of \a n objects of type \a T from heap
94 *
95 * Note that this function implements C++ semantics: the default
96 * constructor of \a T is run for all \a n objects.
97 */
98 template<class T>
99 T* alloc(int n);
100 /**
101 * \brief Delete \a n objects starting at \a b
102 *
103 * Note that this function implements C++ semantics: the destructor
104 * of \a T is run for all \a n objects.
105 */
106 template<class T>
107 void free(T* b, long unsigned int n);
108 /**
109 * \brief Delete \a n objects starting at \a b
110 *
111 * Note that this function implements C++ semantics: the destructor
112 * of \a T is run for all \a n objects.
113 */
114 template<class T>
115 void free(T* b, long int n);
116 /**
117 * \brief Delete \a n objects starting at \a b
118 *
119 * Note that this function implements C++ semantics: the destructor
120 * of \a T is run for all \a n objects.
121 */
122 template<class T>
123 void free(T* b, unsigned int n);
124 /**
125 * \brief Delete \a n objects starting at \a b
126 *
127 * Note that this function implements C++ semantics: the destructor
128 * of \a T is run for all \a n objects.
129 */
130 template<class T>
131 void free(T* b, int n);
132 /**
133 * \brief Reallocate block of \a n objects starting at \a b to \a m objects of type \a T from heap
134 *
135 * Note that this function implements C++ semantics: the copy constructor
136 * of \a T is run for all \f$\min(n,m)\f$ objects, the default
137 * constructor of \a T is run for all remaining
138 * \f$\max(n,m)-\min(n,m)\f$ objects, and the destrucor of \a T is
139 * run for all \a n objects in \a b.
140 *
141 * Returns the address of the new block.
142 */
143 template<class T>
144 T* realloc(T* b, long unsigned int n, long unsigned int m);
145 /**
146 * \brief Reallocate block of \a n objects starting at \a b to \a m objects of type \a T from heap
147 *
148 * Note that this function implements C++ semantics: the copy constructor
149 * of \a T is run for all \f$\min(n,m)\f$ objects, the default
150 * constructor of \a T is run for all remaining
151 * \f$\max(n,m)-\min(n,m)\f$ objects, and the destrucor of \a T is
152 * run for all \a n objects in \a b.
153 *
154 * Returns the address of the new block.
155 */
156 template<class T>
157 T* realloc(T* b, long int n, long int m);
158 /**
159 * \brief Reallocate block of \a n objects starting at \a b to \a m objects of type \a T from heap
160 *
161 * Note that this function implements C++ semantics: the copy constructor
162 * of \a T is run for all \f$\min(n,m)\f$ objects, the default
163 * constructor of \a T is run for all remaining
164 * \f$\max(n,m)-\min(n,m)\f$ objects, and the destrucor of \a T is
165 * run for all \a n objects in \a b.
166 *
167 * Returns the address of the new block.
168 */
169 template<class T>
170 T* realloc(T* b, unsigned int n, unsigned int m);
171 /**
172 * \brief Reallocate block of \a n objects starting at \a b to \a m objects of type \a T from heap
173 *
174 * Note that this function implements C++ semantics: the copy constructor
175 * of \a T is run for all \f$\min(n,m)\f$ objects, the default
176 * constructor of \a T is run for all remaining
177 * \f$\max(n,m)-\min(n,m)\f$ objects, and the destrucor of \a T is
178 * run for all \a n objects in \a b.
179 *
180 * Returns the address of the new block.
181 */
182 template<class T>
183 T* realloc(T* b, int n, int m);
184 /**
185 * \brief Reallocate block of \a n pointers starting at \a b to \a m objects of type \a T* from heap
186 *
187 * Returns the address of the new block.
188 *
189 * This is a specialization for performance.
190 */
191 template<class T>
192 T** realloc(T** b, long unsigned int n, long unsigned int m);
193 /**
194 * \brief Reallocate block of \a n pointers starting at \a b to \a m objects of type \a T* from heap
195 *
196 * Returns the address of the new block.
197 *
198 * This is a specialization for performance.
199 */
200 template<class T>
201 T** realloc(T** b, long int n, long int m);
202 /**
203 * \brief Reallocate block of \a n pointers starting at \a b to \a m objects of type \a T* from heap
204 *
205 * Returns the address of the new block.
206 *
207 * This is a specialization for performance.
208 */
209 template<class T>
210 T** realloc(T** b, unsigned int n, unsigned int m);
211 /**
212 * \brief Reallocate block of \a n pointers starting at \a b to \a m objects of type \a T* from heap
213 *
214 * Returns the address of the new block.
215 *
216 * This is a specialization for performance.
217 */
218 template<class T>
219 T** realloc(T** b, int n, int m);
220 /**
221 * \brief Copy \a n objects starting at \a s to \a d
222 *
223 * Note that this function implements C++ semantics: the assignment
224 * operator of \a T is run for all \a n objects.
225 *
226 * Returns \a d.
227 */
228 template<class T>
229 static T* copy(T* d, const T* s, long unsigned int n);
230 /**
231 * \brief Copy \a n objects starting at \a s to \a d
232 *
233 * Note that this function implements C++ semantics: the assignment
234 * operator of \a T is run for all \a n objects.
235 *
236 * Returns \a d.
237 */
238 template<class T>
239 static T* copy(T* d, const T* s, long int n);
240 /**
241 * \brief Copy \a n objects starting at \a s to \a d
242 *
243 * Note that this function implements C++ semantics: the assignment
244 * operator of \a T is run for all \a n objects.
245 *
246 * Returns \a d.
247 */
248 template<class T>
249 static T* copy(T* d, const T* s, unsigned int n);
250 /**
251 * \brief Copy \a n objects starting at \a s to \a d
252 *
253 * Note that this function implements C++ semantics: the assignment
254 * operator of \a T is run for all \a n objects.
255 *
256 * Returns \a d.
257 */
258 template<class T>
259 static T* copy(T* d, const T* s, int n);
260 /**
261 * \brief Copy \a n pointers starting at \a s to \a d
262 *
263 * Returns \a d.
264 *
265 * This is a specialization for performance.
266 */
267 template<class T>
268 static T** copy(T** d, const T** s, long unsigned int n);
269 /**
270 * \brief Copy \a n pointers starting at \a s to \a d
271 *
272 * Returns \a d.
273 *
274 * This is a specialization for performance.
275 */
276 template<class T>
277 static T** copy(T** d, const T** s, long int n);
278 /**
279 * \brief Copy \a n pointers starting at \a s to \a d
280 *
281 * Returns \a d.
282 *
283 * This is a specialization for performance.
284 */
285 template<class T>
286 static T** copy(T** d, const T** s, unsigned int n);
287 /**
288 * \brief Copy \a n pointers starting at \a s to \a d
289 *
290 * Returns \a d.
291 *
292 * This is a specialization for performance.
293 */
294 template<class T>
295 static T** copy(T** d, const T** s, int n);
296 //@}
297 /// \name Raw allocation routines
298 //@{
299 /// Allocate \a s bytes from heap
300 void* ralloc(size_t s);
301 /// Free memory block starting at \a p
302 void rfree(void* p);
303 /// Free memory block starting at \a p with size \a s
304 void rfree(void* p, size_t s);
305 /// Change memory block starting at \a p to size \a s
306 void* rrealloc(void* p, size_t s);
307 //@}
308#ifdef GECODE_PEAKHEAP
309 private:
310 /// Mutex for accessing heap size
311 Support::FastMutex _m;
312 /// Peak heap size
313 size_t _peak;
314 /// Current heap size
315 size_t _cur;
316public:
317 size_t peak(void);
318#endif
319 /// Allocate memory from heap (disabled)
320 static void* operator new(size_t s) = delete;
321 /// Free memory allocated from heap (disabled)
322 static void operator delete(void* p) = delete;
323 /// Copy constructor (disabled)
324 Heap(const Heap&) = delete;
325 /// Assignment operator (disabled)
326 const Heap& operator =(const Heap&) = delete;
327 };
328
329 /**
330 * \brief The single global heap
331 * \ingroup FuncMemHeap
332 */
333 extern GECODE_SUPPORT_EXPORT
334 Heap heap;
335
336 /**
337 * \brief Base class for heap allocated objects
338 * \ingroup FuncMemHeap
339 */
340 class GECODE_SUPPORT_EXPORT HeapAllocated {
341 public:
342 /// Memory management
343 //@{
344 /// Allocate memory from heap
345 static void* operator new(size_t s);
346 /// Free memory allocated from heap
347 static void operator delete(void* p);
348 //@}
349 };
350
351
352 /*
353 * Wrappers for raw allocation routines
354 *
355 */
356 forceinline void*
357 Heap::ralloc(size_t s) {
358 void* p = Support::allocator.alloc(s);
359#ifdef GECODE_PEAKHEAP
360 _m.acquire();
361 _cur += GECODE_MSIZE(p);
362 _peak = std::max(_peak,_cur);
363 _m.release();
364#endif
365 if (p != nullptr)
366 return p;
367 throw MemoryExhausted();
368 }
369
370 forceinline void
371 Heap::rfree(void* p) {
372#ifdef GECODE_PEAKHEAP
373 _m.acquire();
374 _cur -= GECODE_MSIZE(p);
375 _m.release();
376#endif
377 Support::allocator.free(p);
378 }
379
380 forceinline void
381 Heap::rfree(void* p, size_t) {
382#ifdef GECODE_PEAKHEAP
383 _m.acquire();
384 _cur -= GECODE_MSIZE(p);
385 _m.release();
386#endif
387 Support::allocator.free(p);
388 }
389
390 forceinline void*
391 Heap::rrealloc(void* p, size_t s) {
392#ifdef GECODE_PEAKHEAP
393 _m.acquire();
394 _cur -= GECODE_MSIZE(p);
395 _m.release();
396#endif
397 p = Support::allocator.realloc(p,s);
398#ifdef GECODE_PEAKHEAP
399 _m.acquire();
400 _cur += GECODE_MSIZE(p);
401 _peak = std::max(_peak,_cur);
402 _m.release();
403#endif
404 if (p != nullptr || s == 0)
405 return p;
406 throw MemoryExhausted();
407 }
408
409
410 /*
411 * Heap allocated objects
412 *
413 */
414 forceinline void*
415 HeapAllocated::operator new(size_t s) {
416 return heap.ralloc(s);
417 }
418 forceinline void
419 HeapAllocated::operator delete(void* p) {
420 heap.rfree(p);
421 }
422
423
424
425 /*
426 * Typed allocation routines
427 *
428 */
429 template<class T>
430 forceinline T*
431 Heap::alloc(long unsigned int n) {
432 T* p = static_cast<T*>(ralloc(sizeof(T)*n));
433 for (long unsigned int i=0U; i<n; i++)
434 (void) new (p+i) T();
435 return p;
436 }
437 template<class T>
438 forceinline T*
439 Heap::alloc(long int n) {
440 assert(n >= 0);
441 return alloc<T>(static_cast<long unsigned int>(n));
442 }
443 template<class T>
444 forceinline T*
445 Heap::alloc(unsigned int n) {
446 return alloc<T>(static_cast<long unsigned int>(n));
447 }
448 template<class T>
449 forceinline T*
450 Heap::alloc(int n) {
451 assert(n >= 0);
452 return alloc<T>(static_cast<long unsigned int>(n));
453 }
454
455 template<class T>
456 forceinline void
457 Heap::free(T* b, long unsigned int n) {
458 for (long unsigned int i=0U; i<n; i++)
459 b[i].~T();
460 rfree(b);
461 }
462 template<class T>
463 forceinline void
464 Heap::free(T* b, long int n) {
465 assert(n >= 0);
466 free<T>(b, static_cast<long unsigned int>(n));
467 }
468 template<class T>
469 forceinline void
470 Heap::free(T* b, unsigned int n) {
471 free<T>(b, static_cast<long unsigned int>(n));
472 }
473 template<class T>
474 forceinline void
475 Heap::free(T* b, int n) {
476 assert(n >= 0);
477 free<T>(b, static_cast<long unsigned int>(n));
478 }
479
480 template<class T>
481 forceinline T*
482 Heap::realloc(T* b, long unsigned int n, long unsigned int m) {
483 if (n == m)
484 return b;
485 T* p = static_cast<T*>(ralloc(sizeof(T)*m));
486 for (long unsigned int i=0U; i<std::min(n,m); i++)
487 (void) new (p+i) T(b[i]);
488 for (long unsigned int i=n; i<m; i++)
489 (void) new (p+i) T();
490 free<T>(b,n);
491 return p;
492 }
493 template<class T>
494 forceinline T*
495 Heap::realloc(T* b, long int n, long int m) {
496 assert((n >= 0) && (m >= 0));
497 return realloc<T>(b,static_cast<long unsigned int>(n),
498 static_cast<long unsigned int>(m));
499 }
500 template<class T>
501 forceinline T*
502 Heap::realloc(T* b, unsigned int n, unsigned int m) {
503 return realloc<T>(b,static_cast<long unsigned int>(n),
504 static_cast<long unsigned int>(m));
505 }
506 template<class T>
507 forceinline T*
508 Heap::realloc(T* b, int n, int m) {
509 assert((n >= 0) && (m >= 0));
510 return realloc<T>(b,static_cast<long unsigned int>(n),
511 static_cast<long unsigned int>(m));
512 }
513
514#define GECODE_SUPPORT_REALLOC(T) \
515 template<> \
516 forceinline T* \
517 Heap::realloc<T>(T* b, long unsigned int, long unsigned int m) { \
518 return static_cast<T*>(rrealloc(b,m*sizeof(T))); \
519 } \
520 template<> \
521 forceinline T* \
522 Heap::realloc<T>(T* b, long int n, long int m) { \
523 assert((n >= 0) && (m >= 0)); \
524 return realloc<T>(b,static_cast<long unsigned int>(n), \
525 static_cast<long unsigned int>(m)); \
526 } \
527 template<> \
528 forceinline T* \
529 Heap::realloc<T>(T* b, unsigned int n, unsigned int m) { \
530 return realloc<T>(b,static_cast<long unsigned int>(n), \
531 static_cast<long unsigned int>(m)); \
532 } \
533 template<> \
534 forceinline T* \
535 Heap::realloc<T>(T* b, int n, int m) { \
536 assert((n >= 0) && (m >= 0)); \
537 return realloc<T>(b,static_cast<long unsigned int>(n), \
538 static_cast<long unsigned int>(m)); \
539 }
540
541 GECODE_SUPPORT_REALLOC(bool)
542 GECODE_SUPPORT_REALLOC(signed char)
543 GECODE_SUPPORT_REALLOC(unsigned char)
544 GECODE_SUPPORT_REALLOC(signed short int)
545 GECODE_SUPPORT_REALLOC(unsigned short int)
546 GECODE_SUPPORT_REALLOC(signed int)
547 GECODE_SUPPORT_REALLOC(unsigned int)
548 GECODE_SUPPORT_REALLOC(signed long int)
549 GECODE_SUPPORT_REALLOC(unsigned long int)
550 GECODE_SUPPORT_REALLOC(float)
551 GECODE_SUPPORT_REALLOC(double)
552
553#undef GECODE_SUPPORT_REALLOC
554
555 template<class T>
556 forceinline T**
557 Heap::realloc(T** b, long unsigned int, long unsigned int m) {
558 return static_cast<T**>(rrealloc(b,m*sizeof(T*)));
559 }
560 template<class T>
561 forceinline T**
562 Heap::realloc(T** b, long int n, long int m) {
563 assert((n >= 0) && (m >= 0));
564 return realloc<T*>(b,static_cast<long unsigned int>(n),
565 static_cast<long unsigned int>(m));
566 }
567 template<class T>
568 forceinline T**
569 Heap::realloc(T** b, unsigned int n, unsigned int m) {
570 return realloc<T*>(b,static_cast<long unsigned int>(n),
571 static_cast<long unsigned int>(m));
572 }
573 template<class T>
574 forceinline T**
575 Heap::realloc(T** b, int n, int m) {
576 assert((n >= 0) && (m >= 0));
577 return realloc<T*>(b,static_cast<long unsigned int>(n),
578 static_cast<long unsigned int>(m));
579 }
580
581 template<class T>
582 forceinline T*
583 Heap::copy(T* d, const T* s, long unsigned int n) {
584 for (long unsigned int i=0U; i<n; i++)
585 d[i]=s[i];
586 return d;
587 }
588 template<class T>
589 forceinline T*
590 Heap::copy(T* d, const T* s, long int n) {
591 assert(n >= 0);
592 return copy<T>(d,s,static_cast<long unsigned int>(n));
593 }
594 template<class T>
595 forceinline T*
596 Heap::copy(T* d, const T* s, unsigned int n) {
597 return copy<T>(d,s,static_cast<long unsigned int>(n));
598 }
599 template<class T>
600 forceinline T*
601 Heap::copy(T* d, const T* s, int n) {
602 assert(n >= 0);
603 return copy<T>(d,s,static_cast<long unsigned int>(n));
604 }
605
606#define GECODE_SUPPORT_COPY(T) \
607 template<> \
608 forceinline T* \
609 Heap::copy(T* d, const T* s, long unsigned int n) { \
610 return static_cast<T*>(Support::allocator.memcpy(d,s,n*sizeof(T))); \
611 } \
612 template<> \
613 forceinline T* \
614 Heap::copy(T* d, const T* s, long int n) { \
615 assert(n >= 0); \
616 return copy<T>(d,s,static_cast<long unsigned int>(n)); \
617 } \
618 template<> \
619 forceinline T* \
620 Heap::copy(T* d, const T* s, unsigned int n) { \
621 return copy<T>(d,s,static_cast<long unsigned int>(n)); \
622 } \
623 template<> \
624 forceinline T* \
625 Heap::copy(T* d, const T* s, int n) { \
626 assert(n >= 0); \
627 return copy<T>(d,s,static_cast<long unsigned int>(n)); \
628 }
629
630 GECODE_SUPPORT_COPY(bool)
631 GECODE_SUPPORT_COPY(signed char)
632 GECODE_SUPPORT_COPY(unsigned char)
633 GECODE_SUPPORT_COPY(signed short int)
634 GECODE_SUPPORT_COPY(unsigned short int)
635 GECODE_SUPPORT_COPY(signed int)
636 GECODE_SUPPORT_COPY(unsigned int)
637 GECODE_SUPPORT_COPY(signed long int)
638 GECODE_SUPPORT_COPY(unsigned long int)
639 GECODE_SUPPORT_COPY(float)
640 GECODE_SUPPORT_COPY(double)
641
642#undef GECODE_SUPPORT_COPY
643
644 template<class T>
645 forceinline T**
646 Heap::copy(T** d, const T** s, long unsigned int n) {
647 return static_cast<T**>(Support::allocator.memcpy(d,s,n*sizeof(T*)));
648 }
649 template<class T>
650 forceinline T**
651 Heap::copy(T** d, const T** s, long int n) {
652 assert(n >= 0);
653 return copy<T*>(d,s,static_cast<long unsigned int>(n));
654 }
655 template<class T>
656 forceinline T**
657 Heap::copy(T** d, const T** s, unsigned int n) {
658 return copy<T*>(d,s,static_cast<long unsigned int>(n));
659 }
660 template<class T>
661 forceinline T**
662 Heap::copy(T** d, const T** s, int n) {
663 assert(n >= 0);
664 return copy<T*>(d,s,static_cast<long unsigned int>(n));
665 }
666
667#ifdef GECODE_PEAKHEAP
668 forceinline size_t
669 Heap::peak(void) {
670 _m.acquire();
671 size_t ret = _peak;
672 _m.release();
673 return ret;
674 }
675#endif
676
677}
678
679// STATISTICS: support-any