24 #ifndef ROOFIT_ROOFITCORE_SRC_MEMPOOLFORROOSETS_H_
25 #define ROOFIT_ROOFITCORE_SRC_MEMPOOLFORROOSETS_H_
30 template <
class RooSet_t, std::
size_t POOLSIZE>
31 class MemPoolForRooSets {
35 : ownedMemory{
static_cast<RooSet_t *
>(::operator
new(POOLSIZE *
sizeof(RooSet_t)))},
36 memBegin{ownedMemory}, nextItem{ownedMemory},
37 memEnd{memBegin + POOLSIZE}, refCount{0}
43 Arena(
const Arena &) =
delete;
45 : ownedMemory{other.ownedMemory},
46 memBegin{other.memBegin}, nextItem{other.nextItem}, memEnd{other.memEnd},
47 refCount{other.refCount}
49 , deletedElements { std::move(other.deletedElements) }
53 other.ownedMemory =
nullptr;
59 Arena & operator=(
const Arena &) =
delete;
60 Arena & operator=(Arena && other)
62 ownedMemory = other.ownedMemory;
63 memBegin = other.memBegin;
64 nextItem = other.nextItem;
65 memEnd = other.memEnd;
67 deletedElements = std::move(other.deletedElements);
69 refCount = other.refCount;
71 other.ownedMemory =
nullptr;
83 if (!ownedMemory)
return;
86 std::cerr << __FILE__ <<
":" << __LINE__ <<
"Deleting arena " << ownedMemory <<
" with use count " << refCount
91 ::operator
delete(ownedMemory);
95 bool inPool(
const RooSet_t *
const ptr)
const {
96 return memBegin <= ptr && ptr < memEnd;
99 bool inPool(
const void *
const ptr)
const
101 return inPool(static_cast<const RooSet_t * const>(ptr));
104 bool hasSpace()
const {
return ownedMemory && nextItem < memEnd; }
105 bool empty()
const {
return refCount == 0; }
107 void tryFree(
bool freeNonFull) {
108 if (ownedMemory && empty() && (!hasSpace() || freeNonFull) ) {
109 ::operator
delete(ownedMemory);
110 ownedMemory =
nullptr;
116 if (!hasSpace())
return nullptr;
122 bool tryDeallocate(
void * ptr)
127 const std::size_t index =
static_cast<RooSet_t *
>(ptr) - memBegin;
128 if (deletedElements.count(index) != 0) {
129 std::cerr <<
"Double delete of " << ptr <<
" at index " << index <<
" in Arena with refCount " << refCount
130 <<
".\n\tArena: |" << memBegin <<
"\t" << ptr <<
"\t" << memEnd <<
"|" << std::endl;
133 deletedElements.insert(index);
140 bool memoryOverlaps(
const Arena& other)
const {
142 return inPool(other.memBegin) || inPool(reinterpret_cast<const char*>(other.memEnd)-1);
145 RooSet_t * ownedMemory;
146 const RooSet_t * memBegin;
148 const RooSet_t * memEnd;
149 std::size_t refCount;
151 std::set<std::size_t> deletedElements;
158 MemPoolForRooSets() : fArenas{} {}
160 MemPoolForRooSets(
const MemPoolForRooSets &) =
delete;
161 MemPoolForRooSets(MemPoolForRooSets &&) =
delete;
162 MemPoolForRooSets & operator=(
const MemPoolForRooSets &) =
delete;
163 MemPoolForRooSets & operator=(MemPoolForRooSets &&) =
delete;
170 std::cerr << __PRETTY_FUNCTION__;
172 std::cerr <<
" The mem pool being deleted is not empty. This will lead to crashes."
181 void * allocate(std::size_t bytes)
183 if (bytes !=
sizeof(RooSet_t))
184 throw std::bad_alloc();
186 if (fArenas.empty() || !fArenas.back().hasSpace()) {
191 void * ptr = fArenas.back().tryAllocate();
192 assert(ptr !=
nullptr);
201 bool deallocate(
void * ptr)
203 bool deallocSuccess =
false;
205 if (std::any_of(fArenas.begin(), fArenas.end(),
206 [ptr](Arena& arena){
return arena.tryDeallocate(ptr);})) {
207 deallocSuccess =
true;
215 return deallocSuccess;
226 for (
auto & arena : fArenas) {
227 arena.tryFree(fTeardownMode);
232 std::remove_if(fArenas.begin(), fArenas.end(), [](Arena& ar){
return ar.ownedMemory ==
nullptr;}),
242 return std::all_of(fArenas.begin(), fArenas.end(), [](
const Arena & ar) {
return ar.empty(); });
252 fTeardownMode =
true;
265 std::vector<Arena> failedAllocs;
268 if (std::none_of(fArenas.begin(), fArenas.end(),
269 [&ar](Arena& other){
return ar.memoryOverlaps(other);})) {
270 fArenas.push_back(std::move(ar));
274 failedAllocs.push_back(std::move(ar));
281 std::vector<Arena> fArenas;
282 bool fTeardownMode{
false};