// @(#)root/minuit2:$Id$ // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 /********************************************************************** * * * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * * * **********************************************************************/ #ifndef ROOT_Minuit2_StackAllocator #define ROOT_Minuit2_StackAllocator #include "Minuit2/MnConfig.h" // comment out this line and recompile if you want to gain additional // performance (the gain is mainly for "simple" functions which are easy // to calculate and vanishes quickly if going to cost-intensive functions) // the library is no longer thread save however #ifdef MN_USE_STACK_ALLOC #define _MN_NO_THREAD_SAVE_ #endif #include #include namespace ROOT { namespace Minuit2 { /// define stack allocator symbol class StackOverflow { }; class StackError { }; // using namespace std; /** StackAllocator controls the memory allocation/deallocation of Minuit. If _MN_NO_THREAD_SAVE_ is defined, memory is taken from a pre-allocated piece of heap memory which is then used like a stack, otherwise via standard malloc/free. Note that defining _MN_NO_THREAD_SAVE_ makes the code thread- unsave. The gain in performance is mainly for cost-cheap FCN functions. */ class StackAllocator { public: // enum {default_size = 1048576}; enum { default_size = 524288 }; StackAllocator() : fStack(nullptr) { #ifdef _MN_NO_THREAD_SAVE_ // std::cout<<"StackAllocator Allocate "<(fStack + offset); *ip = Value; } int ToInt(void *p) { unsigned char *pc = static_cast(p); // std::cout << "toInt: p = " << p << " fStack = " << (void*) fStack << std::endl; // VC 7.1 warning:conversion from __w64 int to int int userBlock = pc - fStack; return userBlock - sizeof(int); // correct for starting int } int AlignedSize(int nBytes) { const int fAlignment = 4; int needed = nBytes % fAlignment == 0 ? nBytes : (nBytes / fAlignment + 1) * fAlignment; return needed + 2 * sizeof(int); } void CheckOverflow(int n) { if (fStackOffset + n >= default_size) { // std::cout << " no more space on stack allocator" << std::endl; throw StackOverflow(); } } bool CheckConsistency() { // std::cout << "checking consistency for " << fBlockCount << " blocks"<< std::endl; // loop over all blocks int beg = 0; int end = fStackOffset; int nblocks = 0; while (beg < fStackOffset) { end = ReadInt(beg); // std::cout << "beg = " << beg << " end = " << end // << " fStackOffset = " << fStackOffset << std::endl; int beg2 = ReadInt(end - sizeof(int)); if (beg != beg2) { // std::cout << " beg != beg2 " << std::endl; return false; } nblocks++; beg = end; } if (end != fStackOffset) { // std::cout << " end != fStackOffset" << std::endl; return false; } if (nblocks != fBlockCount) { // std::cout << "nblocks != fBlockCount" << std::endl; return false; } // std::cout << "Allocator is in consistent state, nblocks = " << nblocks << std::endl; return true; } private: unsigned char *fStack; // unsigned char fStack[default_size]; int fStackOffset; int fBlockCount; }; class StackAllocatorHolder { // t.b.d need to use same trick as Boost singleton.hpp to be sure that // StackAllocator is created before main() public: static StackAllocator &Get() { static StackAllocator gStackAllocator; return gStackAllocator; } }; } // namespace Minuit2 } // namespace ROOT #endif