Garfield++ 3.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
FunNameStack.h
Go to the documentation of this file.
1#ifndef FUNNAMESTACK_H
2#define FUNNAMESTACK_H
3
4/*
5Copyright (c) 1999 I. B. Smirnov
6
7Permission to use, copy, modify, distribute and sell this file
8and its documentation for any purpose is hereby granted without fee,
9provided that the above copyright notice, this permission notice,
10and notices about any modifications of the original text
11appear in all copies and in supporting documentation.
12It is provided "as is" without express or implied warranty.
13*/
14
15#include <list>
16#include <iostream>
17#include <cstdlib>
19
20//#define USE_BOOST_MULTITHREADING
21//#define PRINT_MESSAGE_ABOUT_THREAD_INITIALIZATION
22// Prints a long message at initialization of FunNameStack.
23// The message is quite long and it is unlikely that
24// it can be visually missed even if it is interrupted by play of threads.
25// This message is not necessary in routine work.
26
27#ifdef USE_BOOST_MULTITHREADING
28#include "boost/thread/mutex.hpp"
29#endif
30
31/*
32// Here there is a good place to switch off the
33// initialization of the function names in all the programs
34#ifdef FUNNAMESTACK
35#undef FUNNAMESTACK
36#endif
37*/
38
39// Switch on/off initialization of function names.
40#ifdef FUNNAMESTACK
41#define mfunname(string) \
42 static const char* FunNameIIII = string; \
43 FunNameWatch funnw(FunNameIIII)
44#else
45#define mfunname(string)
46#endif
47
48// Permanent definitions
49#define mfunnamep(string) \
50 static const char* FunNameIIII = string; \
51 FunNameWatch funnw(FunNameIIII)
52
53// Switch on/off checks
54#define DO_CHECKS
55#ifdef DO_CHECKS
56
57#ifdef FUNNAMESTACK
58
59#define check_econd1(condition, a1, stream) \
60 if (condition) { \
61 funnw.ehdr(stream); \
62 stream << '\n' << #condition << '\n'; \
63 stream << #a1 << '=' << (a1) << '\n'; \
64 spexit(stream); \
65 }
66#define check_wcond1(condition, a1, stream) \
67 if (condition) { \
68 funnw.whdr(stream); \
69 stream << '\n' << #condition << '\n'; \
70 stream << #a1 << '=' << (a1) << '\n'; \
71 }
72
73#define check_econd11(a, signb, stream) \
74 if (a signb) { \
75 funnw.ehdr(stream); \
76 stream << '\n' << #a << #signb << '\n'; \
77 stream << #a << '=' << (a) << '\n'; \
78 spexit(stream); \
79 }
80
81#define check_econd12(a, sign, b, stream) \
82 if (a sign b) { \
83 funnw.ehdr(stream); \
84 stream << '\n' << #a << #sign << #b << '\n'; \
85 stream << #a << '=' << (a) << ' ' << #b << '=' << (b) << '\n'; \
86 spexit(stream); \
87 }
88
89// condition + additional any commands
90#define check_econd11a(a, signb, add, stream) \
91 if (a signb) { \
92 funnw.ehdr(stream); \
93 stream << '\n' << #a << #signb << '\n'; \
94 stream << #a << '=' << (a) << '\n'; \
95 stream << add; \
96 spexit(stream); \
97 }
98
99#define check_econd12a(a, sign, b, add, stream) \
100 if (a sign b) { \
101 funnw.ehdr(stream); \
102 stream << '\n' << #a << #sign << #b << '\n'; \
103 stream << #a << '=' << (a) << ' ' << #b << '=' << (b) << '\n'; \
104 stream << add; \
105 spexit(stream); \
106 }
107
108// and of two conditions for one variable
109#define check_econd21(a, sign1_b1_sign0, sign2_b2, stream) \
110 if (a sign1_b1_sign0 a sign2_b2) { \
111 funnw.ehdr(stream); \
112 stream << '\n' << #a << #sign1_b1_sign0 << #a << #sign2_b2 << '\n'; \
113 stream << #a << '=' << (a) << '\n'; \
114 spexit(stream); \
115 }
116
117// and of two conditions for one variable
118#define check_econd23(a, sign1, b1, sign0, sign2, b2, stream) \
119 if (a sign1 b1 sign0 a sign2 b2) { \
120 funnw.ehdr(stream); \
121 stream << '\n' << #a << #sign1 << #b1 << #sign0 << #a << #sign2 << #b2 \
122 << '\n'; \
123 stream << #a << '=' << (a) << ' ' << #b1 << '=' << (b1) << ' ' << #b2 \
124 << '=' << (b2) << '\n'; \
125 spexit(stream); \
126 }
127
128// two conditions for four variables
129#define check_econd24(a1, sign1, b1, sign0, a2, sign2, b2, stream) \
130 if (a1 sign1 b1 sign0 a2 sign2 b2) { \
131 funnw.ehdr(stream); \
132 stream << '\n' << #a1 << #sign1 << #b1 << #sign0 << #a2 << #sign2 << #b2 \
133 << '\n'; \
134 stream << #a1 << '=' << (a1) << ' ' << #b1 << '=' << (b1) << '\n'; \
135 stream << #a2 << '=' << (a2) << ' ' << #b2 << '=' << (b2) << '\n'; \
136 spexit(stream); \
137 }
138
139#else // without FUNNAMESTACK, print only condition
140
141#define check_econd1(condition, a1, stream) \
142 if (condition) { \
143 stream << "ERROR:\n"; \
144 stream << '\n' << #condition << '\n'; \
145 stream << #a1 << '=' << (a1) << '\n'; \
146 spexit(stream); \
147 }
148#define check_wcond1(condition, a1, stream) \
149 if (condition) { \
150 stream << "WARNING:\n"; \
151 stream << '\n' << #condition << '\n'; \
152 stream << #a1 << '=' << (a1) << '\n'; \
153 }
154
155#define check_econd11(a, signb, stream) \
156 if (a signb) { \
157 stream << "ERROR:\n"; \
158 stream << '\n' << #a << #signb << '\n'; \
159 stream << #a << '=' << (a) << '\n'; \
160 spexit(stream); \
161 }
162
163#define check_econd12(a, sign, b, stream) \
164 if (a sign b) { \
165 stream << "ERROR:\n"; \
166 stream << '\n' << #a << #sign << #b << '\n'; \
167 stream << #a << '=' << (a) << ' ' << #b << '=' << (b) << '\n'; \
168 spexit(stream); \
169 }
170
171// condition + additional any commands
172#define check_econd11a(a, signb, add, stream) \
173 if (a signb) { \
174 stream << "ERROR:\n"; \
175 stream << '\n' << #a << #signb << '\n'; \
176 stream << #a << '=' << (a) << '\n'; \
177 stream << add; \
178 spexit(stream); \
179 }
180
181#define check_econd12a(a, sign, b, add, stream) \
182 if (a sign b) { \
183 stream << "ERROR:\n"; \
184 stream << '\n' << #a << #sign << #b << '\n'; \
185 stream << #a << '=' << (a) << ' ' << #b << '=' << (b) << '\n'; \
186 stream << add; \
187 spexit(stream); \
188 }
189
190// and of two conditions for one variable
191#define check_econd21(a, sign1_b1_sign0, sign2_b2, stream) \
192 if (a sign1_b1_sign0 a sign2_b2) { \
193 stream << "ERROR:\n"; \
194 stream << '\n' << #a << #sign1_b1_sign0 << #a << #sign2_b2 << '\n'; \
195 stream << #a << '=' << (a) << '\n'; \
196 spexit(stream); \
197 }
198
199// and of two conditions for one variable
200#define check_econd23(a, sign1, b1, sign0, sign2, b2, stream) \
201 if (a sign1 b1 sign0 a sign2 b2) { \
202 stream << "ERROR:\n"; \
203 stream << '\n' << #a << #sign1 << #b1 << #sign0 << #a << #sign2 << #b2 \
204 << '\n'; \
205 stream << #a << '=' << (a) << ' ' << #b1 << '=' << (b1) << ' ' << #b2 \
206 << '=' << (b2) << '\n'; \
207 spexit(stream); \
208 }
209
210// two conditions for four variables
211#define check_econd24(a1, sign1, b1, sign0, a2, sign2, b2, stream) \
212 if (a1 sign1 b1 sign0 a2 sign2 b2) { \
213 stream << "ERROR:\n"; \
214 stream << '\n' << #a1 << #sign1 << #b1 << #sign0 << #a2 << #sign2 << #b2 \
215 << '\n'; \
216 stream << #a1 << '=' << (a1) << ' ' << #b1 << '=' << (b1) << '\n'; \
217 stream << #a2 << '=' << (a2) << ' ' << #b2 << '=' << (b2) << '\n'; \
218 spexit(stream); \
219 }
220
221#endif
222
223#else // without checks
224
225#define check_econd1(condition, a1, stream)
226#define check_wcond1(condition, a1, stream)
227
228#define check_econd11(a, signb, stream)
229#define check_econd12(a, sign, b, stream)
230#define check_econd11a(a, signb, add, stream)
231#define check_econd12a(a, sign, b, add, stream)
232// and of two conditions for one variable
233#define check_econd21(a, sign1_b1_sign0, sign2_b2, stream)
234// and of two conditions for one variable
235#define check_econd23(a, sign1, b1, sign0, sign2, b2, stream)
236// two conditions for four variables
237#define check_econd24(a1, sign1, b1, sign0, a2, sign2, b2, stream)
238
239#endif
240
241namespace Heed {
242
244 public:
246};
247
248void spexit_action(std::ostream& file);
249extern int s_throw_exception_in_spexit; // if == 1, does exit(1) of abort()
250 // depending on the key below
251extern int s_exit_without_core; // the key above have larger priority
252
253}
254
255// Normal exit:
256#define spexit(stream) \
257 { \
258 stream << FunNameStack::instance(); \
259 stream << "File is " << __FILE__ << " , line number is " << __LINE__ \
260 << '\n'; \
261 spexit_action(stream); \
262 }
263
264// Converting to a quasi-singleton class:
265// The program operates only with main hidden exsemplar.
266// Nothing could be copied to, but it itself can be copied,
267// for example for passing with exception classes
268
269#ifdef USE_BOOST_MULTITHREADING
270/* For multithreading we will keep own stack for each thread.
271This complicates things a lot, but still managable.
272In one thread case the stack data qname and name[] are kept directly
273in a singleton object of FunNameStack class.
274For multithreading mode we need to introduce special intermediate class
275NameStack and initialize one object of this class per each found thread.
276*/
277
278class NameStack {
279 public:
280 static const int pqname = 1000;
281 // this depth of stack is completely OK for all correct programs.
282 // If you have overflow, it is likely the infinite loop with recursion
283 // in your program!
284 int qname;
285 char* name[pqname];
286 pthread_t id;
287 int nmode; // 0 - name points to a string in outside world
288 // used for global object funnamestack
289 // 1 - name is inited by new and deleted by delete
290 // may be used for sending as parameter of exception
291 // It is not convenient for normal work due
292 // to time expense
293 NameStack(void) : qname(0), id(0), nmode(0) {
294 for (int n = 0; n < pqname; n++) name[n] = NULL;
295 }
296 NameStack(const NameStack& f) : qname(0), id(0), nmode(0) { *this = f; }
297
298 NameStack& operator=(const NameStack& f);
299
300 ~NameStack(void) {
301 if (nmode == 1)
302 for (int n = 0; n < qname; n++) delete name[n];
303 }
304};
305#endif
306
307namespace Heed {
308
310 public:
311 static FunNameStack& instance();
312
313 // make instances of the class uncopyable to hidden exsemplar,
314 // but copyable away.
315 //
316
317 FunNameStack(const FunNameStack& f);
319
320 FunNameStack(void); // usually called inly from instance()
321 private:
322#ifdef USE_BOOST_MULTITHREADING
323 // Two next functions return NameStack corresponding to
324 // current thread.
325 NameStack* get_thread_stack(void) const;
326 NameStack* get_thread_stack_q(long& nthread, long& qthread) const;
327 // retrieve not only NameStack, but also nthread and qthread.
328
329 void remove_thread_stack(void);
330#endif
331#ifdef USE_BOOST_MULTITHREADING
332 std::list<NameStack>* namestack;
333// Cannot put ActivePtr here because it uses FunNameStack itself
334// and wants it to be completed.
335#else
336 int qname;
337 static const int pqname = 1000;
338 char* name[pqname];
339#endif
340 int s_init; // 1 - sign that it is inited,
341 // any other value - not inited
342 // Now this variable is used only for debug printing.
343
344 int s_act; // 1 - active, 0 - not active
345 //( to switch without recompilation)
346 public:
347 int s_print; // works only is s_act=1;
348 // 0 - no print
349 // 1 - at each entry print the name of current function
350 // 2 - at each entry and each exit
351 // print the name of current function
352 // 3 - at each entry print all stack
353 // 4 - at each entry and exit print all stack
354 private:
355 int nmode; // 0 - name points to a string in outside world
356 // used for global object funnamestack
357 // 1 - name is inited by new and deleted by delete
358 // may be used for sending as parameter of exception
359 // It is not convenient for normal work due
360 // to time expense
361
362#ifdef USE_BOOST_MULTITHREADING
363 std::ostream& printname(std::ostream& file, NameStack* ns, int n);
364#else
365 std::ostream& printname(std::ostream& file, int n);
366#endif
367 public:
368 void set_parameters(int fs_act = 1, int fs_print = 0);
370
371 private:
372 void printput(std::ostream& file); // called at insertion of new name in
373 // stack
374 void printdel(std::ostream& file); // called at deletion of name from stack
375 public:
376 inline int put(const char* fname);
377 inline void del(int nname);
378 inline void replace(const char* fname);
379 friend std::ostream& operator<<(std::ostream& file, const FunNameStack& f);
380};
381std::ostream& operator<<(std::ostream& file, const FunNameStack& f);
382
383// Object of this class FunNameWatch is created at the beginning of function.
384// At creation it writes function name in stack.
385// At deletion it deletes the name from stack,
386// checking that it is last.
387
389 int nname; // index of this name in array of FunNameStack
390 const char* name; // it is memorized independenlty on s_act.
391 // Used for printing of headers.
392 public:
393 inline FunNameWatch(const char* fname);
395
396 // print header
397 std::ostream& hdr(std::ostream& file) const {
398 file << name << ": ";
399 return file;
400 }
401 // print header with word WARNING
402 std::ostream& whdr(std::ostream& file) const {
403 file << name << ": WARNING:\n";
404 return file;
405 }
406 // print header with word ERROR
407 std::ostream& ehdr(std::ostream& file) const {
408 file << name << ": ERROR:\n";
409 return file;
410 }
411};
412std::ostream& operator<<(std::ostream& file, const FunNameWatch& f);
413
414#include "wcpplib/util/FunNameStack.ic"
415
416}
417
418#endif
friend std::ostream & operator<<(std::ostream &file, const FunNameStack &f)
void del(int nname)
static FunNameStack & instance()
FunNameStack & operator=(const FunNameStack &f)
void replace(const char *fname)
void set_parameters(int fs_act=1, int fs_print=0)
int put(const char *fname)
std::ostream & ehdr(std::ostream &file) const
Definition: FunNameStack.h:407
std::ostream & whdr(std::ostream &file) const
Definition: FunNameStack.h:402
FunNameWatch(const char *fname)
std::ostream & hdr(std::ostream &file) const
Definition: FunNameStack.h:397
Definition: BGMesh.cpp:6
std::ostream & operator<<(std::ostream &file, const BGMesh &bgm)
Definition: BGMesh.cpp:37
void spexit_action(std::ostream &file)
int s_exit_without_core
int s_throw_exception_in_spexit