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
38/** StackAllocator controls the memory allocation/deallocation of Minuit. If
39 _MN_NO_THREAD_SAVE_ is defined, memory is taken from a pre-allocated piece
40 of heap memory which is then used like a stack, otherwise via standard
41 malloc/free. Note that defining _MN_NO_THREAD_SAVE_ makes the code thread-
42 unsave. The gain in performance is mainly for cost-cheap FCN functions.
43 */
44
46
47public:
48 // enum {default_size = 1048576};
49 enum { default_size = 524288 };
50
52 {
53#ifdef _MN_NO_THREAD_SAVE_
54 // std::cout<<"StackAllocator Allocate "<<default_size<<std::endl;
55 fStack = new unsigned char[default_size];
56#endif
57 fStackOffset = 0;
58 fBlockCount = 0;
59 }
60
62 {
63#ifdef _MN_NO_THREAD_SAVE_
64 // std::cout<<"StackAllocator destruct "<<fStackOffset<<std::endl;
65 if (fStack)
66 delete[] fStack;
67#endif
68 }
69
70 void *Allocate(size_t nBytes)
71 {
72#ifdef _MN_NO_THREAD_SAVE_
73 if (fStack == 0)
74 fStack = new unsigned char[default_size];
75 int nAlloc = AlignedSize(nBytes);
76 CheckOverflow(nAlloc);
77
78 // std::cout << "Allocating " << nAlloc << " bytes, requested = " << nBytes << std::endl;
79
80 // write the start position of the next block at the start of the block
82 // write the start position of the new block at the end of the block
83 WriteInt(fStackOffset + nAlloc - sizeof(int), fStackOffset);
84
85 void *result = fStack + fStackOffset + sizeof(int);
86 fStackOffset += nAlloc;
88
89#ifdef DEBUG_ALLOCATOR
91#endif
92
93#else
94 void *result = malloc(nBytes);
95 if (!result)
96 throw std::bad_alloc();
97#endif
98
99 return result;
100 }
101
102 void Deallocate(void *p)
103 {
104#ifdef _MN_NO_THREAD_SAVE_
105 // int previousOffset = ReadInt( fStackOffset - sizeof(int));
106 int delBlock = ToInt(p);
107 int nextBlock = ReadInt(delBlock);
108 int previousBlock = ReadInt(nextBlock - sizeof(int));
109 if (nextBlock == fStackOffset) {
110 // deallocating last allocated
111 fStackOffset = previousBlock;
112 } else {
113 // overwrite previous adr of next block
114 int nextNextBlock = ReadInt(nextBlock);
115 WriteInt(nextNextBlock - sizeof(int), previousBlock);
116 // overwrite head of deleted block
117 WriteInt(previousBlock, nextNextBlock);
118 }
119 fBlockCount--;
120
121#ifdef DEBUG_ALLOCATOR
123#endif
124#else
125 free(p);
126#endif
127 // std::cout << "Block at " << delBlock
128 // << " deallocated, fStackOffset = " << fStackOffset << std::endl;
129 }
130
132 {
133 int *ip = (int *)(fStack + offset);
134
135 // std::cout << "read " << *ip << " from offset " << offset << std::endl;
136
137 return *ip;
138 }
139
140 void WriteInt(int offset, int Value)
141 {
142
143 // std::cout << "writing " << Value << " to offset " << offset << std::endl;
144
145 int *ip = reinterpret_cast<int *>(fStack + offset);
146 *ip = Value;
147 }
148
149 int ToInt(void *p)
150 {
151 unsigned char *pc = static_cast<unsigned char *>(p);
152
153 // std::cout << "toInt: p = " << p << " fStack = " << (void*) fStack << std::endl;
154 // VC 7.1 warning:conversion from __w64 int to int
155 int userBlock = pc - fStack;
156 return userBlock - sizeof(int); // correct for starting int
157 }
158
159 int AlignedSize(int nBytes)
160 {
161 const int fAlignment = 4;
162 int needed = nBytes % fAlignment == 0 ? nBytes : (nBytes / fAlignment + 1) * fAlignment;
163 return needed + 2 * sizeof(int);
164 }
165
166 void CheckOverflow(int n)
167 {
168 if (fStackOffset + n >= default_size) {
169 // std::cout << " no more space on stack allocator" << std::endl;
170 throw StackOverflow();
171 }
172 }
173
175 {
176
177 // std::cout << "checking consistency for " << fBlockCount << " blocks"<< std::endl;
178
179 // loop over all blocks
180 int beg = 0;
181 int end = fStackOffset;
182 int nblocks = 0;
183 while (beg < fStackOffset) {
184 end = ReadInt(beg);
185
186 // std::cout << "beg = " << beg << " end = " << end
187 // << " fStackOffset = " << fStackOffset << std::endl;
188
189 int beg2 = ReadInt(end - sizeof(int));
190 if (beg != beg2) {
191 // std::cout << " beg != beg2 " << std::endl;
192 return false;
193 }
194 nblocks++;
195 beg = end;
196 }
197 if (end != fStackOffset) {
198 // std::cout << " end != fStackOffset" << std::endl;
199 return false;
200 }
201 if (nblocks != fBlockCount) {
202 // std::cout << "nblocks != fBlockCount" << std::endl;
203 return false;
204 }
205 // std::cout << "Allocator is in consistent state, nblocks = " << nblocks << std::endl;
206 return true;
207 }
208
209private:
210 unsigned char *fStack;
211 // unsigned char fStack[default_size];
214};
215
217
218 // t.b.d need to use same trick as Boost singleton.hpp to be sure that
219 // StackAllocator is created before main()
220
221public:
223 {
224 static StackAllocator gStackAllocator;
225 return gStackAllocator;
226 }
227};
228
229} // namespace Minuit2
230
231} // namespace ROOT
232
233#endif
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
#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
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.