24#ifndef ROOFIT_ROOFITCORE_SRC_MEMPOOLFORROOSETS_H_
25#define ROOFIT_ROOFITCORE_SRC_MEMPOOLFORROOSETS_H_
34template <
class RooSet_t, std::
size_t POOLSIZE>
39 :
ownedMemory{static_cast<RooSet_t *>(
TStorage::ObjectAlloc(2 * POOLSIZE * sizeof(RooSet_t)))},
47 : ownedMemory{other.ownedMemory},
48 memBegin{other.memBegin}, nextItem{other.nextItem}, memEnd{other.memEnd},
49 refCount{other.refCount},
50 totCount{other.totCount},
51 assigned{other.assigned},
55 other.ownedMemory =
nullptr;
65 memBegin = other.memBegin;
66 nextItem = other.nextItem;
67 memEnd = other.memEnd;
68 refCount = other.refCount;
69 totCount = other.totCount;
70 assigned = other.assigned;
72 other.ownedMemory =
nullptr;
84 if (!ownedMemory)
return;
87 std::cerr << __FILE__ <<
":" << __LINE__ <<
"Deleting arena " << ownedMemory <<
" with use count " << refCount
92 ::operator
delete(ownedMemory);
96 bool inPool(
const RooSet_t *
const ptr)
const {
97 return memBegin <= ptr && ptr < memEnd;
100 bool inPool(
const void *
const ptr)
const
102 return inPool(
static_cast<const RooSet_t * const
>(ptr));
106 return totCount < POOLSIZE *
sizeof(RooSet_t) && refCount < POOLSIZE;
108 bool empty()
const {
return refCount == 0; }
111 if (ownedMemory && empty() && (!hasSpace() || freeNonFull) ) {
112 ::operator
delete(ownedMemory);
113 ownedMemory =
nullptr;
119 if (!hasSpace())
return nullptr;
121 for(std::size_t i = 0; i < POOLSIZE; ++i) {
122 if (nextItem == memEnd) {
123 nextItem = ownedMemory;
125 std::size_t index = (
static_cast<RooSet_t *
>(nextItem) - memBegin) / 2;
127 if(!assigned[index]) {
128 if (cycle[index] ==
sizeof(RooSet_t)) {
133 assigned[index] =
true;
134 auto ptr =
reinterpret_cast<RooSet_t*
>(
reinterpret_cast<char*
>(ownedMemory + 2 * index) + cycle[index]);
148 const std::size_t index = ( (
reinterpret_cast<const char *
>(ptr) -
reinterpret_cast<const char *
>(memBegin)) / 2) /
sizeof(RooSet_t);
150 if (assigned[index] ==
false) {
151 std::cerr <<
"Double delete of " << ptr <<
" at index " << index <<
" in Arena with refCount " << refCount
152 <<
".\n\tArena: |" << memBegin <<
"\t" << ptr <<
"\t" << memEnd <<
"|" << std::endl;
156 assigned[index] =
false;
164 return inPool(other.
memBegin) || inPool(
reinterpret_cast<const char*
>(other.
memEnd)-1);
171 std::size_t refCount = 0;
172 std::size_t totCount = 0;
174 std::bitset<POOLSIZE> assigned = {};
175 std::array<int, POOLSIZE> cycle = {{}};
193 std::cerr << __PRETTY_FUNCTION__;
195 std::cerr <<
" The mem pool being deleted is not empty. This will lead to crashes."
204 if (bytes !=
sizeof(RooSet_t))
205 throw std::bad_alloc();
207 if (fArenas.empty()) {
211 void * ptr = fArenas.back().tryAllocate();
213 if (ptr ==
nullptr) {
216 ptr = fArenas.back().tryAllocate();
219 assert(ptr !=
nullptr);
230 bool deallocSuccess =
false;
232 if (std::any_of(fArenas.begin(), fArenas.end(),
233 [ptr](
Arena& arena){return arena.tryDeallocate(ptr);})) {
234 deallocSuccess =
true;
242 return deallocSuccess;
253 for (
auto & arena : fArenas) {
254 arena.tryFree(fTeardownMode);
259 std::remove_if(fArenas.begin(), fArenas.end(), [](
Arena& ar){return ar.ownedMemory == nullptr;}),
269 return std::all_of(fArenas.begin(), fArenas.end(), [](
const Arena & ar) { return ar.empty(); });
279 fTeardownMode =
true;
292 std::vector<Arena> failedAllocs;
295 if (std::none_of(fArenas.begin(), fArenas.end(),
296 [&ar](
Arena& other){return ar.memoryOverlaps(other);})) {
297 fArenas.emplace_back(std::move(ar));
301 failedAllocs.push_back(std::move(ar));
309 bool fTeardownMode{
false};
Memory pool for RooArgSet and RooDataSet.
~MemPoolForRooSets()
Destructor. Should not be called when RooArgSets or RooDataSets are still alive.
void prune()
Free memory in arenas that don't have space and no users.
MemPoolForRooSets & operator=(const MemPoolForRooSets &)=delete
MemPoolForRooSets(const MemPoolForRooSets &)=delete
void newArena()
RooFit relies on unique pointers for RooArgSets.
MemPoolForRooSets & operator=(MemPoolForRooSets &&)=delete
MemPoolForRooSets()
Create empty mem pool.
void * allocate(std::size_t bytes)
Allocate memory for the templated set type. Fails if bytes != sizeof(RooSet_t).
bool deallocate(void *ptr)
Deallocate memory for the templated set type if in pool.
MemPoolForRooSets(MemPoolForRooSets &&)=delete
void teardown()
Set pool to teardown mode (at program end).
std::vector< Arena > fArenas
bool empty() const
Test if pool is empty.
bool tryDeallocate(void *ptr)
void tryFree(bool freeNonFull)
bool inPool(const void *const ptr) const
bool memoryOverlaps(const Arena &other) const
const RooSet_t * memBegin
std::array< int, POOLSIZE > cycle
Arena & operator=(Arena &&other)
bool inPool(const RooSet_t *const ptr) const
Arena(const Arena &)=delete
Arena & operator=(const Arena &)=delete