Logo ROOT  
Reference Guide
StackAllocator.h
Go to the documentation of this file.
1 // @(#)root/minuit2:$Id$
2 // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005
3 
4 /**********************************************************************
5  * *
6  * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT *
7  * *
8  **********************************************************************/
9 
10 #ifndef ROOT_Minuit2_StackAllocator
11 #define ROOT_Minuit2_StackAllocator
12 
13 #include "Minuit2/MnConfig.h"
14 
15 // comment out this line and recompile if you want to gain additional
16 // performance (the gain is mainly for "simple" functions which are easy
17 // to calculate and vanishes quickly if going to cost-intensive functions)
18 // the library is no longer thread save however
19 
20 #ifdef MN_USE_STACK_ALLOC
21 #define _MN_NO_THREAD_SAVE_
22 #endif
23 
24 #include <cstdlib>
25 #include <new>
26 
27 namespace ROOT {
28 
29 namespace Minuit2 {
30 
31 /// define stack allocator symbol
32 
34 };
35 class StackError {
36 };
37 // using namespace std;
38 
39 /** StackAllocator controls the memory allocation/deallocation of Minuit. If
40  _MN_NO_THREAD_SAVE_ is defined, memory is taken from a pre-allocated piece
41  of heap memory which is then used like a stack, otherwise via standard
42  malloc/free. Note that defining _MN_NO_THREAD_SAVE_ makes the code thread-
43  unsave. The gain in performance is mainly for cost-cheap FCN functions.
44  */
45 
47 
48 public:
49  // enum {default_size = 1048576};
50  enum { default_size = 524288 };
51 
53  {
54 #ifdef _MN_NO_THREAD_SAVE_
55  // std::cout<<"StackAllocator Allocate "<<default_size<<std::endl;
56  fStack = new unsigned char[default_size];
57 #endif
58  fStackOffset = 0;
59  fBlockCount = 0;
60  }
61 
63  {
64 #ifdef _MN_NO_THREAD_SAVE_
65  // std::cout<<"StackAllocator destruct "<<fStackOffset<<std::endl;
66  if (fStack)
67  delete[] fStack;
68 #endif
69  }
70 
71  void *Allocate(size_t nBytes)
72  {
73 #ifdef _MN_NO_THREAD_SAVE_
74  if (fStack == 0)
75  fStack = new unsigned char[default_size];
76  int nAlloc = AlignedSize(nBytes);
77  CheckOverflow(nAlloc);
78 
79  // std::cout << "Allocating " << nAlloc << " bytes, requested = " << nBytes << std::endl;
80 
81  // write the start position of the next block at the start of the block
83  // write the start position of the new block at the end of the block
84  WriteInt(fStackOffset + nAlloc - sizeof(int), fStackOffset);
85 
86  void *result = fStack + fStackOffset + sizeof(int);
87  fStackOffset += nAlloc;
88  fBlockCount++;
89 
90 #ifdef DEBUG_ALLOCATOR
92 #endif
93 
94 #else
95  void *result = malloc(nBytes);
96  if (!result)
97  throw std::bad_alloc();
98 #endif
99 
100  return result;
101  }
102 
103  void Deallocate(void *p)
104  {
105 #ifdef _MN_NO_THREAD_SAVE_
106  // int previousOffset = ReadInt( fStackOffset - sizeof(int));
107  int delBlock = ToInt(p);
108  int nextBlock = ReadInt(delBlock);
109  int previousBlock = ReadInt(nextBlock - sizeof(int));
110  if (nextBlock == fStackOffset) {
111  // deallocating last allocated
112  fStackOffset = previousBlock;
113  } else {
114  // overwrite previous adr of next block
115  int nextNextBlock = ReadInt(nextBlock);
116  WriteInt(nextNextBlock - sizeof(int), previousBlock);
117  // overwrite head of deleted block
118  WriteInt(previousBlock, nextNextBlock);
119  }
120  fBlockCount--;
121 
122 #ifdef DEBUG_ALLOCATOR
124 #endif
125 #else
126  free(p);
127 #endif
128  // std::cout << "Block at " << delBlock
129  // << " deallocated, fStackOffset = " << fStackOffset << std::endl;
130  }
131 
132  int ReadInt(int offset)
133  {
134  int *ip = (int *)(fStack + offset);
135 
136  // std::cout << "read " << *ip << " from offset " << offset << std::endl;
137 
138  return *ip;
139  }
140 
141  void WriteInt(int offset, int Value)
142  {
143 
144  // std::cout << "writing " << Value << " to offset " << offset << std::endl;
145 
146  int *ip = reinterpret_cast<int *>(fStack + offset);
147  *ip = Value;
148  }
149 
150  int ToInt(void *p)
151  {
152  unsigned char *pc = static_cast<unsigned char *>(p);
153 
154  // std::cout << "toInt: p = " << p << " fStack = " << (void*) fStack << std::endl;
155  // VC 7.1 warning:conversin from __w64 int to int
156  int userBlock = pc - fStack;
157  return userBlock - sizeof(int); // correct for starting int
158  }
159 
160  int AlignedSize(int nBytes)
161  {
162  const int fAlignment = 4;
163  int needed = nBytes % fAlignment == 0 ? nBytes : (nBytes / fAlignment + 1) * fAlignment;
164  return needed + 2 * sizeof(int);
165  }
166 
167  void CheckOverflow(int n)
168  {
169  if (fStackOffset + n >= default_size) {
170  // std::cout << " no more space on stack allocator" << std::endl;
171  throw StackOverflow();
172  }
173  }
174 
176  {
177 
178  // std::cout << "checking consistency for " << fBlockCount << " blocks"<< std::endl;
179 
180  // loop over all blocks
181  int beg = 0;
182  int end = fStackOffset;
183  int nblocks = 0;
184  while (beg < fStackOffset) {
185  end = ReadInt(beg);
186 
187  // std::cout << "beg = " << beg << " end = " << end
188  // << " fStackOffset = " << fStackOffset << std::endl;
189 
190  int beg2 = ReadInt(end - sizeof(int));
191  if (beg != beg2) {
192  // std::cout << " beg != beg2 " << std::endl;
193  return false;
194  }
195  nblocks++;
196  beg = end;
197  }
198  if (end != fStackOffset) {
199  // std::cout << " end != fStackOffset" << std::endl;
200  return false;
201  }
202  if (nblocks != fBlockCount) {
203  // std::cout << "nblocks != fBlockCount" << std::endl;
204  return false;
205  }
206  // std::cout << "Allocator is in consistent state, nblocks = " << nblocks << std::endl;
207  return true;
208  }
209 
210 private:
211  unsigned char *fStack;
212  // unsigned char fStack[default_size];
215 };
216 
218 
219  // t.b.d need to use same trick as Boost singleton.hpp to be sure that
220  // StackAllocator is created before main()
221 
222 public:
223  static StackAllocator &Get()
224  {
225  static StackAllocator gStackAllocator;
226  return gStackAllocator;
227  }
228 };
229 
230 } // namespace Minuit2
231 
232 } // namespace ROOT
233 
234 #endif
n
const Int_t n
Definition: legend1.C:16
ROOT::Minuit2::StackAllocator::~StackAllocator
~StackAllocator()
Definition: StackAllocator.h:62
ROOT::Minuit2::StackAllocatorHolder
Definition: StackAllocator.h:217
ROOT::Minuit2::StackAllocator::ReadInt
int ReadInt(int offset)
Definition: StackAllocator.h:132
ROOT::Minuit2::StackAllocator::CheckConsistency
bool CheckConsistency()
Definition: StackAllocator.h:175
ROOT::Minuit2::StackAllocator::Deallocate
void Deallocate(void *p)
Definition: StackAllocator.h:103
ROOT::Minuit2::StackAllocator::ToInt
int ToInt(void *p)
Definition: StackAllocator.h:150
ROOT::Minuit2::StackAllocator::AlignedSize
int AlignedSize(int nBytes)
Definition: StackAllocator.h:160
TGeant4Unit::pc
static constexpr double pc
Definition: TGeant4SystemOfUnits.h:130
ROOT::Minuit2::StackAllocator::fStackOffset
int fStackOffset
Definition: StackAllocator.h:213
ROOT::Minuit2::StackAllocator::fBlockCount
int fBlockCount
Definition: StackAllocator.h:214
ROOT::Minuit2::StackAllocator
StackAllocator controls the memory allocation/deallocation of Minuit.
Definition: StackAllocator.h:46
ROOT::Minuit2::StackAllocator::default_size
@ default_size
Definition: StackAllocator.h:50
ROOT::Minuit2::StackAllocator::StackAllocator
StackAllocator()
Definition: StackAllocator.h:52
malloc
#define malloc
Definition: civetweb.c:1536
xmlio::Value
const char * Value
Definition: TXMLSetup.cxx:73
ROOT::Minuit2::StackError
Definition: StackAllocator.h:35
Value
Definition: functioncalls.h:15
ROOT::Minuit2::StackAllocator::CheckOverflow
void CheckOverflow(int n)
Definition: StackAllocator.h:167
ROOT::Minuit2::StackAllocator::Allocate
void * Allocate(size_t nBytes)
Definition: StackAllocator.h:71
ROOT::Minuit2::StackAllocatorHolder::Get
static StackAllocator & Get()
Definition: StackAllocator.h:223
ROOT::Minuit2::StackOverflow
define stack allocator symbol
Definition: StackAllocator.h:33
free
#define free
Definition: civetweb.c:1539
ROOT
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Definition: EExecutionPolicy.hxx:4
ROOT::Minuit2::StackAllocator::WriteInt
void WriteInt(int offset, int Value)
Definition: StackAllocator.h:141
MnConfig.h
int
ROOT::Minuit2::StackAllocator::fStack
unsigned char * fStack
Definition: StackAllocator.h:211