24#ifndef ROOFIT_ROOFITCORE_SRC_MEMPOOLFORROOSETS_H_ 
   25#define ROOFIT_ROOFITCORE_SRC_MEMPOOLFORROOSETS_H_ 
   32template <
class RooSet_t, std::
size_t POOLSIZE>
 
   37      : 
ownedMemory{static_cast<RooSet_t *>(::operator new(2 * POOLSIZE * sizeof(RooSet_t)))},
 
   45      : ownedMemory{other.ownedMemory},
 
   46        memBegin{other.memBegin}, nextItem{other.nextItem}, memEnd{other.memEnd},
 
   47        refCount{other.refCount},
 
   48        totCount{other.totCount},
 
   49        assigned{other.assigned},
 
   53      other.ownedMemory = 
nullptr;
 
   63      memBegin = other.memBegin;
 
   64      nextItem = other.nextItem;
 
   65      memEnd   = other.memEnd;
 
   66      refCount     = other.refCount;
 
   67      totCount     = other.totCount;
 
   68      assigned     = other.assigned;
 
   70      other.ownedMemory = 
nullptr;
 
   82      if (!ownedMemory) 
return;
 
   85        std::cerr << __FILE__ << 
":" << __LINE__ << 
"Deleting arena " << ownedMemory << 
" with use count " << refCount
 
   90      ::operator 
delete(ownedMemory);
 
   94    bool inPool(
const RooSet_t * 
const ptr)
 const {
 
   95      return memBegin <= ptr && ptr < memEnd;
 
   98    bool inPool(
const void * 
const ptr)
 const 
  100      return inPool(
static_cast<const RooSet_t * const
>(ptr));
 
  104        return totCount < POOLSIZE * 
sizeof(RooSet_t) && refCount < POOLSIZE;
 
  106    bool empty()
 const { 
return refCount == 0; }
 
  109      if (ownedMemory && empty() && (!hasSpace() || freeNonFull) ) {
 
  110        ::operator 
delete(ownedMemory);
 
  111        ownedMemory = 
nullptr;
 
  117      if (!hasSpace()) 
return nullptr;
 
  119      for(std::size_t i = 0; i < POOLSIZE; ++i) {
 
  120        if (nextItem == memEnd) {
 
  121          nextItem = ownedMemory;
 
  123        std::size_t index = (
static_cast<RooSet_t *
>(nextItem) - memBegin) / 2;
 
  125        if(!assigned[index]) {
 
  126          if (cycle[index] == 
sizeof(RooSet_t)) {
 
  131          assigned[index] = 
true;
 
  132          auto ptr = 
reinterpret_cast<RooSet_t*
>(
reinterpret_cast<char*
>(ownedMemory + 2 * index) + cycle[index]);
 
  146        const std::size_t index = ( (
reinterpret_cast<const char *
>(ptr) - 
reinterpret_cast<const char *
>(memBegin)) / 2) / 
sizeof(RooSet_t);
 
  148        if (assigned[index] == 
false) {
 
  149          std::cerr << 
"Double delete of " << ptr << 
" at index " << index << 
" in Arena with refCount " << refCount
 
  150              << 
".\n\tArena: |" << memBegin << 
"\t" << ptr << 
"\t" << memEnd << 
"|" << std::endl;
 
  154        assigned[index] = 
false;
 
  162      return inPool(other.
memBegin) || inPool(
reinterpret_cast<const char*
>(other.
memEnd)-1);
 
  169    std::size_t refCount = 0;
 
  170    std::size_t totCount = 0;
 
  172    std::bitset<POOLSIZE> assigned = {};
 
  173    std::array<int, POOLSIZE> cycle = {{}};
 
  191      std::cerr << __PRETTY_FUNCTION__;
 
  193      std::cerr << 
" The mem pool being deleted is not empty. This will lead to crashes." 
  202    if (bytes != 
sizeof(RooSet_t))
 
  203      throw std::bad_alloc();
 
  205    if (fArenas.empty()) {
 
  209    void * ptr = fArenas.back().tryAllocate();
 
  211    if (ptr == 
nullptr) {
 
  214      ptr = fArenas.back().tryAllocate();
 
  217    assert(ptr != 
nullptr);
 
  228    bool deallocSuccess = 
false;
 
  230    if (std::any_of(fArenas.begin(), fArenas.end(),
 
  231      [ptr](
Arena& arena){return arena.tryDeallocate(ptr);})) {
 
  232        deallocSuccess = 
true;
 
  240    return deallocSuccess;
 
  251    for (
auto & arena : fArenas) {
 
  252      arena.tryFree(fTeardownMode);
 
  257          std::remove_if(fArenas.begin(), fArenas.end(), [](
Arena& ar){return ar.ownedMemory == nullptr;}),
 
  267    return std::all_of(fArenas.begin(), fArenas.end(), [](
const Arena & ar) { return ar.empty(); });
 
  277    fTeardownMode = 
true;
 
  290    std::vector<Arena> failedAllocs;
 
  293      if (std::none_of(fArenas.begin(), fArenas.end(),
 
  294          [&ar](
Arena& other){return ar.memoryOverlaps(other);})) {
 
  295        fArenas.emplace_back(std::move(ar));
 
  299        failedAllocs.push_back(std::move(ar));
 
  307  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