1 /****************************************************************************
2  * Core Library Version 1.7, August 2004
3  * Copyright (c) 1995-2004 Exact Computation Project
4  * All rights reserved.
5  *
6  * This file is part of CGAL (www.cgal.org).
7  *
8  * File: MemoryPool.h
9  * Synopsis:
10  *      a memory pool template class.
11  *
12  * Written by
13  *       Zilin Du <zilin@cs.nyu.edu>
14  *       Chee Yap <yap@cs.nyu.edu>
15  *       Sylvain Pion <pion@cs.nyu.edu>
16  *
17  * WWW URL: http://cs.nyu.edu/exact/
18  * Email: exact@cs.nyu.edu
19  *
20  * $URL: https://github.com/CGAL/cgal/blob/v5.3/CGAL_Core/include/CGAL/CORE/MemoryPool.h $
21  * $Id: MemoryPool.h 8a7d3fa 2020-07-21T17:32:30+02:00 Laurent Rineau
22  * SPDX-License-Identifier: LGPL-3.0-or-later
23  ***************************************************************************/
24 #ifndef _CORE_MEMORYPOOL_H_
25 #define _CORE_MEMORYPOOL_H_
26 
27 #include <CGAL/config.h>
28 #include <CGAL/tss.h>
29 
30 #include <new>           // for placement new
31 #include <cassert>
32 #include <CGAL/assertions.h>
33 #include <vector>
34 
35 namespace CORE {
36 
37 #define CORE_EXPANSION_SIZE 1024
38 template< class T, int nObjects = CORE_EXPANSION_SIZE >
39 class MemoryPool {
40 private:
41    struct Thunk {
42       T object;
43       Thunk* next;
44    };
45 
46   typedef MemoryPool<T,nObjects> Self;
47 public:
MemoryPool()48    MemoryPool() : head( 0 ) {}
49 
~MemoryPool()50   ~MemoryPool()
51   {
52     //CGAL_warning_code(
53       std::size_t count = 0;
54       Thunk* t = head;
55       while(t!=0){
56         ++count;
57         t = t->next;
58       }
59     //);
60     //CGAL_warning_msg(count ==  nObjects * blocks.size(),
61     //                 "Cannot delete memory as there are cyclic references");
62 
63     if(count ==  nObjects * blocks.size()){
64       for(std::size_t i=0; i < blocks.size();i++){
65         ::operator delete(blocks[i]);
66       }
67     }
68     // un-commenting the following line can help reproduce on Linux the
69     // assertion !blocks.empty() that is sometimes triggered with MSVC
70     // or AppleClang
71     // blocks.clear();
72   }
73 
74 
75    void* allocate(std::size_t size);
76    void free(void* p);
77 
78   // Access the corresponding static global allocator.
global_allocator()79   static MemoryPool<T,nObjects>& global_allocator() {
80 #if defined(CGAL_HAS_THREADS) // use the C++11 implementation
81     static thread_local Self memPool;
82 #else // not CGAL_HAS_THREADS
83     static Self memPool;
84 #endif // not CGAL_HAS_THREADS
85     return memPool;
86   }
87 
88 private:
89    Thunk* head; // next available block in the pool
90   std::vector<void*> blocks;
91 };
92 
93 template< class T, int nObjects >
allocate(std::size_t)94 void* MemoryPool< T, nObjects >::allocate(std::size_t) {
95    if ( head == 0 ) { // if no more memory in the pool
96       const int last = nObjects - 1;
97 
98       // use the global operator new to allocate a block for the pool
99       Thunk* pool = reinterpret_cast<Thunk*>(
100          ::operator new(nObjects * sizeof(Thunk)));
101 
102       blocks.push_back(pool);
103       // initialize the chain (one-directional linked list)
104       head = pool;
105       for (int i = 0; i < last; ++i ) {
106          pool[i].next = &pool[i+1];
107       }
108       pool[last].next = 0;
109    }
110 
111    // set head to point to the next object in the list
112    Thunk* currentThunk = head;
113    head = currentThunk->next;
114 
115    return currentThunk;
116 }
117 
118 template< class T, int nObjects >
free(void * t)119 void MemoryPool< T, nObjects >::free(void* t) {
120    CGAL_assertion(t != 0);
121    if (t == 0) return; // for safety
122    if(blocks.empty()){
123      std::cerr << typeid(T).name() << std::endl;
124    }
125    CGAL_assertion (! blocks.empty());
126 
127    // recycle the object memory, by putting it back into the chain
128    reinterpret_cast<Thunk*>(t)->next = head;
129    head = reinterpret_cast<Thunk*>(t);
130 }
131 
132 } //namespace CORE
133 
134 #endif // _CORE_MEMORYPOOL_H_
135