Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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
27namespace ROOT {
28
29namespace Minuit2 {
30
31/// define stack allocator symbol
32
34};
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
48public:
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;
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
210private:
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
222public:
224 {
225 static StackAllocator gStackAllocator;
226 return gStackAllocator;
227 }
228};
229
230} // namespace Minuit2
231
232} // namespace ROOT
233
234#endif
#define free
Definition civetweb.c:1539
#define malloc
Definition civetweb.c:1536
static StackAllocator & Get()
StackAllocator controls the memory allocation/deallocation of Minuit.
void WriteInt(int offset, int Value)
void * Allocate(size_t nBytes)
define stack allocator symbol
const Int_t n
Definition legend1.C:16
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...