Garfield++ v2r0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
AbsPtr.h
Go to the documentation of this file.
1#ifndef ABSCONT_H
2#define ABSCONT_H
3/*
4Copyright (c) 1999-2004 I. B. Smirnov
5
6The file can be used, copied, modified, and distributed
7according to the terms of GNU Lesser General Public License version 2.1
8as published by the Free Software Foundation,
9and provided 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.
12The file is provided "as is" without express or implied warranty.
13*/
14
15#include <iostream>
16#include <cstring>
17#include <limits.h>
18#include <typeinfo>
20
21//#define IMPLICIT_X_STAR
22
23#define USE_DOUBLE_PTR_IN_PASSIVEPTR
24// New option. Makes passive ptr keeping address of counter and address
25// of object. This allow to avoid dynamic casts while still allowing
26// the class RegPassivePtr be virtual.
27
28//#define USE_CHECK_DOUBLE_PTR_IN_PASSIVEPTR
29// for debug of the option above. At each access it checks
30// that the object address in ptr is equal to the address
31// restored from the counter.
32
33#define USE_DELETE_AT_ZERO_COUNT
34// to switch on option for emulation of shared pointer.
35// But it only gives possibility to emulate it by the passive pointer,
36// but does not make passive pointer equival to shared one.
37// You should assign 1 to s_allow_del_at_zero_count of each particular object,
38// which should be deleted.
39
40//#define SKIP_CHECKS_NULL // skip checks of smart pointers
41// (that they are not NULL) at
42// dereferencing via getver(), *, and ->.
43// In all cases at the normal execution the object should not be NULL
44// for these operators.
45// Skiping checks, we assume that they are not NULL
46// (and risk to have bad undetected errors at the execution time).
47// This option is incerted due to curiosity about for how much
48// the checks delay the program.
49// For Monte Carlo simulation the result was a few percent.
50// Therefore the use (uncommenting) of this macro for the purposes
51// other than similar curiosity does NOT have any sense.
52
53// To be addressed by active pointer an object of a class
54// should have a function copy() which clones the object and returns
55// the new address, and may have have a function print()
56// which prints it to a stream.
57// The copy() is declared pure just to ensure that the user does not
58// forget to define it in derivative.
59
60#define COPY_TYPE_CHECK // make execution longer, but allows
61// to detect missings of copy functions in classes referred by
62// active pointers.
63
64//#define DEBUG_ACTIVEPTR
65// print some messages at running ActivePtr components
66
67#define USE_GETSETTERS_IN_PASSIVEPTR // new option allowing to use
68// getters and setters in the passive pointer
69// instead or in addition to direct access to auxiliary parameters.
70// It allows to control correctness of input values and also to use
71// fields if the next option is switched on. But note that using fields
72// can increase the size of the code.
73// Switching this option on does not forbid to use direct access to
74// these parameters.
75
76#define USE_PRIVATE_PARAM_IN_PASSIVEPTR // allows to change parameters
77 // only through getters and setters.
78// Obviously, switching this option on requires switching on the previous
79// option, which is controlled by the following:
80#if defined(USE_PRIVATE_PARAM_IN_PASSIVEPTR) && \
81 !defined(USE_GETSETTERS_IN_PASSIVEPTR)
82"options incompatible\n"; // any line to trigger compiler diagnostic
83#endif
84
85#define USE_CHAR_CONTROL_VARIABLES // instead of int control variables
86// enables to use char control variables (except two static ones),
87// which could be optimal
88// both for memory and speed, but that it is really optimal
89// is not checked so far.
90
91//#define USE_BIT_FIELDS // instead of int control variables
92// allowes to pack control auxiliary
93// variables presented in passive pointer into bit fields.
94// It is assumed that the passive pointer objects and the whole
95// programs using it could be smaller in size with this option switched on.
96// But be informed that according to Stroustrup this is not always the fact:
97// this reduces the data but increases the executable code size.
98// Also the performance could be
99// decreased due to necessity to unpack these thinigs each time at their use.
100// This option does not compatible with the previous one.
101// So only one of them can be switched on, which is checked by the following:
102
103//#define USE_BIT_OPERA // Instead of the two previous options
104// allowes to pack control auxiliary
105// variables presented in passive pointer into bit fields
106// and to use bit operations.
107// Currently under debug.
108#if defined(USE_CHAR_CONTROL_VARIABLES) && defined(USE_BIT_FIELDS)
109"options incompatible\n"; // any line to trigger compiler diagnostic
110#endif
111#if defined(USE_CHAR_CONTROL_VARIABLES) && defined(USE_BIT_OPERA)
112"options incompatible\n"; // any line to trigger compiler diagnostic
113#endif
114#if defined(USE_BIT_FIELDS) && defined(USE_BIT_OPERA)
115"options incompatible\n"; // any line to trigger compiler diagnostic
116#endif
117
118#define USE_CHAR_GETSETTERS_PARAMETERS // related to type of parameters
119 // in gatters and setters.
120// If this macro is enabled, the parameters are "char".
121// Otherwise the parameters and int.
122// What is faster I do not know at the moment
123// They are not bool since in many instanses they can have the values
124// of 0, 1, or 2 (and the author does not like bool type at all).
125#if defined(USE_CHAR_CONTROL_VARIABLES) && \
126 !defined(USE_CHAR_GETSETTERS_PARAMETERS)
127"options incompatible\n"; // any line to trigger compiler diagnostic
128#endif
129
130namespace Heed {
131
132template <class X>
134 public:
135 static X* copy(const X* f) {
136#ifdef DEBUG_ACTIVEPTR
137 mcout << "static X* StandardCopyDefinition::copy(const X* f)\n";
138#endif
139 // If to allow the type of copy function be any (void* for example,
140 // it needs to convert it. This seems there is no reason to allow this.
141#ifndef COPY_TYPE_CHECK
142 return f->copy();
143#else
144 X* p = f->copy();
145#ifdef DEBUG_ACTIVEPTR
146 mcout << "X* StandardCopyDefinition::copy(const X* f): f->copy() returned "
147 << p << '\n';
148 mcerr << "Type of X is (in internal notations) " << typeid(X).name()
149 << '\n';
150 mcerr << "Type of *p is (in internal notations) " << typeid(*p).name()
151 << '\n';
152#endif
153 if (typeid(*p) != typeid(*f)) {
154 mcerr << "Error in X* StandardCopyDefinition::copy(const X* f): "
155 << "typeid(*p) != typeid(*f) \n";
156 mcerr << "Type of X is (in internal notations) " << typeid(X).name()
157 << '\n';
158 mcerr << "Type of *p is (in internal notations) " << typeid(*p).name()
159 << '\n';
160 mcerr << "Type of *f is (in internal notations) " << typeid(*f).name()
161 << '\n';
162 mcerr << "Possible reason is omiting of copy function in one of the "
163 "derivative classes\n";
164 spexit(mcerr);
165 }
166 return p;
167#endif
168 }
169};
170
171/* The second parameter determines the class which has to have only one
172function copy() which "knows" the actual name of cloning function.
173Normally the cloning function is copy() as well.
174But can be any.
175Previously at this place there were some terrible comment
176which told that there might be some problems. But it was outdated.
177At contemporary systems there is no problems.
178So any complicated tree of derived classes even with multiple inheritance
179can each have the same-named function
180returning different types with accordance with
181the type of the class.
182Everything is compiled and work.
183But do not forget to add virtual destructors in pointee classes!
184In particular, when playing with multiple inheritance.
185*/
186
187enum Pilfer {
188 steal
190enum Clone {
193enum Pass {
196
197/// Active pointer or automatic container or controlling pointer.
198template <class X, class C = StandardCopyDefinition<X> >
200 public:
201 // First of all, two pointer's operations.
202 // NULL address is interpreted as error.
203 inline X* operator->(void) const;
204 inline X& operator*(void) const;
205
206 // get with verification, that is the same as two operators above,
207 // but with sintax of function:
208 inline X* getver(void) const;
209
210#ifdef IMPLICIT_X_STAR
211 inline operator X*(void) const;
212#endif
213
214 // Then, gentle exctraction of pointer without check:
215 inline X* get(void) const { return ptr; }
216
217 // Two variants of putting the object under control of the pointer:
218 // 1. put(): with cloning
219 // (the ActivePtr will keep copy of what is found at fptr).
220 // 2. pass(): with incerting given address under control
221 // (the ActivePtr will keep fptr, which should be address of
222 // block of dynamic memory).
223 // The old kept object in deleted in both cases.
224 //
225 inline void put(const X* fptr) {
226 // delete old owned object and copy object fptr to ownership of this.
227 // At fptr == NULL old object is deleted and new one is not copied.
228#ifdef DEBUG_ACTIVEPTR
229 mcout << "inline void put(const X* fptr)\n";
230 Iprintn(mcout, ptr);
231 mcout << "Type of X is (in internal notations) " << typeid(X).name()
232 << '\n';
233 mcout << "Type of *fptr is (in internal notations) " << typeid(*fptr).name()
234 << '\n';
235#endif
236 // Initialization of copy should go ahead, since
237 // object *fptr could be dependant or part of *this,
238 // and could be deleted prior to copying at the reverse order.
239 X* ptr_temp = (fptr != NULL ? C::copy(fptr) : (X*)(NULL));
240 if (ptr) delete ptr;
241 ptr = ptr_temp;
242#ifdef DEBUG_ACTIVEPTR
243 mcout << "finishing inline void put(const X* fptr):\n";
244 Iprintn(mcout, ptr);
245#endif
246 }
247 inline void pass(X* fptr) {
248 // delete old owned object and
249 // pass address of object fptr to ownership of this
250 // without copying.
251 // At fptr==NULL old object is deleted and new one is not copyed.
252 // In general this is dengerous operation.
253 // In particular if object pointed by fptr is direct or indirect part
254 // of object pointed by ptr, it will be destroyed, which would probably
255 // cause error.
256 // But it is more efficient since does not require copying.
257
258 if (ptr) {
259 if (fptr) {
260 mcerr << "ERROR in ActivePtr::pass(X* fptr):\n";
261 mcerr << "Both the destination and source pointers are not empty\n";
262 // if f belongs to *ptr, deletion of *ptr would lead to
263 // deletion of f. In order to avoid this unexpected behaviour,
264 // we interprete non-zero ptr as error.
265 // The user should clear ptr first and then use this function.
266 spexit(mcerr);
267 } else {
268 delete ptr;
269 }
270 }
271 ptr = fptr;
272 }
273
274 // Removing the object from the responsibility of smart pointer
275 // without copying
276 inline X* extract(void) {
277 X* ret = ptr;
278 ptr = NULL;
279 return ret;
280 }
281 inline void clear(void) {
282#ifdef DEBUG_ACTIVEPTR
283 mcout << "ActivePtr::clear is called, ptr =" << ptr << '\n';
284#endif
285 if (ptr) {
286 delete ptr;
287 ptr = NULL;
288 }
289 }
290
291 inline void pilfer(const ActivePtr<X, C>& f) {
292 //!Attention: actually not const
293#ifdef DEBUG_ACTIVEPTR
294 mcout << "ActivePtr::pilfer is called\n";
295#endif
296 if (this != &f) {
297 if (ptr) {
298 if (f.ptr) {
299 mcerr << "ERROR in ActivePtr::pilfer(...):\n";
300 mcerr << "Both the destination and source pointers are not empty\n";
301 // if f belongs to *ptr, deletion of *ptr would lead to
302 // deletion of f. In order to avoid this unexpected behaviour,
303 // we interprete non-zero ptr as error.
304 // The user should clear ptr first and then use this function.
305 spexit(mcerr);
306 } else {
307 delete ptr;
308 }
309 }
310 ptr = f.ptr;
311 f.ptr = NULL;
312 }
313 return;
314 }
315
316 void print(std::ostream& file, int l = 1) const;
317 inline ActivePtr(void) : ptr(NULL) {}
318
319 inline ActivePtr(const X* fptr, Clone)
320 : ptr(fptr != NULL ? C::copy(fptr) : ((X*)NULL))
321#ifndef DEBUG_ACTIVEPTR
322 {
323 } // normal case
324#else
325 {
326 mcout << "ActivePtr(const X* fptr, Clone) is finished, ptr =" << ptr
327 << '\n';
328 delete ptr;
329 cout << "deleted, exit\n";
330 exit(0);
331 }
332// debug
333#endif
334 inline ActivePtr(const ActivePtr<X, C>& f)
335 : ptr(f.ptr != NULL ? C::copy(f.ptr) : f.ptr)
336#ifndef DEBUG_ACTIVEPTR
337 {
338 }
339#else
340 {
341 mcout << "ActivePtr(const ActivePtr<X,C>& f) is finished\n";
342 } // debug
343#endif
344
345 // Pilfer constructor
347 : ptr(f.ptr) { //!Attention: actually not const
348#ifdef DEBUG_ACTIVEPTR
349 mcout << "ActivePtr(const ActivePtr<X,C>& f, Pilfer) is run\n";
350#endif
351 f.ptr = NULL;
352 } // debug
353
354 // Pass constructor
355 inline ActivePtr(X* fptr, Pass) : ptr(fptr) {}
356
358#ifdef DEBUG_ACTIVEPTR
359 mcout << "inline ActivePtr& operator=(const ActivePtr<X,C>& f)\n";
360#endif
361 if (this != &f) put(f.ptr);
362 return *this;
363 }
364
365 virtual ActivePtr* copy() const { return new ActivePtr(*this); }
366 virtual ~ActivePtr() {
367 // unfortunately it should be virtual
368 // in order to avoid some rare (not met in practice but
369 // in principle possible) problems with ActivePtrReg.
370 // Therefore (if there is a virtual member)
371 // we can also include virtual copy (see above),
372 // although there is no obvious application for it
373 // (multiple indirection depth, but for what?).
374 if (ptr != NULL) {
375 delete ptr;
376 ptr = NULL;
377 }
378 }
379 // the last assignment is for debug to assure the fast detection of error
380 // in the case of continuing access to this ptr.
381 private:
382 mutable X* ptr; // mutable is only to allow pilfer function and pilfer
383 // constructor to have const descriptor of its argument and still to steal
384 // the object.
385 // Somewhy if without const, this function and this constructor
386 // is sometimes not recognized by Scientific Linux 4.1 compiler.
387 // (when argument is temporary, actual at receiving return value).
388};
389
390template <class X, class C>
391void ActivePtr<X, C>::print(std::ostream& file, int l) const {
392 Ifile << "ActivePtr<X,C>: ";
393 if (ptr == NULL)
394 file << " ptr==NULL. \n"; // optimized to provide automatic reading
395 else {
396 file << " ptr!=NULL: ";
397 file << noindent;
398 ptr->print(file, l);
399 file << yesindent;
400 }
401}
402
403template <class X, class C>
404std::ostream& operator<<(std::ostream& file, const ActivePtr<X, C>& f) {
405 Ifile << "ActivePtr<X,C>: ";
406 if (f.get() == NULL)
407 file << " ptr==NULL. \n"; // optimized to provide automatic reading
408 else {
409 file << " ptr!=NULL: ";
410 file << noindent;
411 file << (*f.get());
412 file << yesindent;
413 }
414
415 return file;
416}
417
418template <class X, class C>
419std::istream& operator>>(std::istream& file, ActivePtr<X, C>& f) {
420 long q = 13;
421 long n;
422 char keyline[13];
423 for (n = 0; n < q - 1; n++) {
424 keyline[n] = file.get();
425 }
426 keyline[n] = '\0';
427 if (!strcmp(&(keyline[0]), " ptr==NULL. ")) {
428 f.clear();
429 } else {
430 X x;
431 file >> x;
432 f.put(x);
433 }
434 return file;
435}
436
437template <class X, class C>
438inline X* ActivePtr<X, C>::operator->(void) const {
439#ifdef SKIP_CHECKS_NULL
440 return ptr;
441#else
442 if (ptr) return ptr;
443 mcerr << "Error in X* ActivePtr<X,C>::operator->(void) const: "
444 << " ptr == NULL\n";
445 mcerr << "Type of X is (in internal notations) " << typeid(X).name() << '\n';
446 // mcerr<<"Type of ptr is "<<typeid(ptr).name()<<'\n';
447 spexit(mcerr);
448 return ptr;
449#endif
450}
451template <class X, class C>
452inline X& ActivePtr<X, C>::operator*(void) const {
453#ifdef SKIP_CHECKS_NULL
454 return *ptr;
455#else
456 if (ptr) return *ptr;
457 mcerr << "Error in X& ActivePtr<X,C>::operator*(void) const: "
458 << " ptr == NULL\n";
459 mcerr << "Type of X is (in internal notations) " << typeid(X).name() << '\n';
460 spexit(mcerr);
461 return *ptr;
462#endif
463}
464template <class X, class C>
465inline X* ActivePtr<X, C>::getver(void) const {
466#ifdef SKIP_CHECKS_NULL
467 return ptr;
468#else
469 if (ptr) return ptr;
470 mcerr << "Error in X* ActivePtr<X,C>::getver(void) const: "
471 << " ptr == NULL\n";
472 mcerr << "Type of X is (in internal notations) " << typeid(X).name() << '\n';
473 spexit(mcerr);
474 return ptr;
475#endif
476}
477#ifdef IMPLICIT_X_STAR
478template <class X, class C>
479inline ActivePtr<X, C>::operator X*(void) const {
480#ifdef SKIP_CHECKS_NULL
481 return ptr;
482#else
483 if (ptr) return ptr;
484 mcerr << "Error in ActivePtr<X,C>::operator X*(void) const: "
485 << " ptr == NULL\n";
486 mcerr << "Type of X is (in internal notations) " << typeid(X).name() << '\n';
487 spexit(mcerr);
488 return ptr;
489#endif
490}
491#endif
492template <class X, class C>
494 X* ptr = f1.extract();
495 f1.pass(f2.extract());
496 f2.pass(ptr);
497}
498
499template <class X>
500class PassivePtr;
501
502class RegPassivePtr;
503
504namespace CountPP_ns {
505/// Counter of protected pointers.
507 public:
508 CountPassivePtr(const RegPassivePtr* frpp) : rpp(frpp), number_of_booked(0) {}
509
510 // In the following I will use the word book instead of register,
511 // because register seems to be interfered with some computer definition
512 inline void book(void);
513 inline void unbook(void);
514 inline long get_number_of_booked(void) { return number_of_booked; }
515 inline const RegPassivePtr* get_rpp(void) { return rpp; }
516 inline void change_rpp(const RegPassivePtr* frpp) { rpp = frpp; }
517 inline ~CountPassivePtr(); // here to delete reference from RegPassivePtr
518 private:
519 const RegPassivePtr* rpp;
520 // const is necessary here to make possible booking of RegPassivePtr
521 // by a function which is declared as const.
522
523 long number_of_booked; // the counter of pointers
524};
525
526inline void CountPassivePtr::book(void) {
527 if (number_of_booked > LONG_MAX - 1) {
528 mcerr << "Error in CountPassivePtr::book(void):\n"
529 << " too much booked counters, number_of_booked > LONG_MAX-1, "
530 "number_of_booked=" << number_of_booked << '\n';
531 spexit(mcerr);
532 }
533 number_of_booked++;
534}
535
536inline void CountPassivePtr::unbook(void) {
537 if (number_of_booked < 1) {
538 mcerr << "Error in CountPassivePtr::unbook(void):\n"
539 << " number_of_booked < 1, number_of_booked=" << number_of_booked
540 << '\n';
541 spexit(mcerr);
542 }
543 number_of_booked--;
544}
545}
546
547#ifdef USE_BIT_OPERA
548
549const unsigned char eb_s_ban_del = 1;
550const unsigned char eb_s_ban_sub1 = 2;
551const unsigned char eb_s_ban_sub2 = 4;
552const unsigned char eb_s_ban_cop1 = 8;
553const unsigned char eb_s_ban_cop2 = 16;
554#ifdef USE_DELETE_AT_ZERO_COUNT
555const unsigned char eb_s_allow_del_at_zero_count = 32;
556#endif
557#endif
558
560 public:
562// used for making cpp NULL when CountPassivePtr
563// is destructed
564
565#ifdef USE_BIT_OPERA
566 private:
567 inline static void clear_bit(unsigned char& cw, unsigned char b) {
568 if ((cw & b) != 0) {
569 cw ^= b;
570 }
571 }
572 inline static void rise_bit(unsigned char& cw, unsigned char b) { cw |= b; }
573
574 public:
575// To define auxiliary class, used only in the following case:
576#elif defined(USE_BIT_FIELDS)
577 class ControlParam {
578 public:
579 unsigned int s_ban_del : 1; // see below for comments
580 unsigned int s_ban_sub : 2;
581 unsigned int s_ban_cop : 2;
582#ifdef USE_DELETE_AT_ZERO_COUNT
583 unsigned int s_allow_del_at_zero_count : 1;
584#endif
585 ControlParam(void)
586 : s_ban_del(0),
587 s_ban_sub(0),
588 s_ban_cop(0)
590 ,
591 s_allow_del_at_zero_count(0)
592#endif
593 {
594 }
595#ifdef USE_CHAR_GETSETTERS_PARAMETERS
596 ControlParam(char fs_ban_del, char fs_ban_sub, char fs_ban_cop = 0
598 ,
599 char fs_allow_del_at_zero_count = 0
600#endif
601 )
602 :
603#else
604 ControlParam(int fs_ban_del, int fs_ban_sub, int fs_ban_cop = 0
606 ,
607 int fs_allow_del_at_zero_count = 0
608#endif
609 )
610 :
611#endif
612 s_ban_del(fs_ban_del),
613 s_ban_sub(fs_ban_sub),
614 s_ban_cop(fs_ban_cop)
616 ,
617 s_allow_del_at_zero_count(fs_allow_del_at_zero_count)
618#endif
619 {
620 if (!(fs_ban_del == 0 || fs_ban_del == 1)) {
621 mcerr << "ERROR in ControlParam::ControlParam(...)\n";
622 mcerr << "s_ban_del is outside limits, s_ban_del=" << fs_ban_del
623 << '\n';
624 spexit(mcerr);
625 }
626 if (fs_ban_sub < 0 || fs_ban_sub > 2) {
627 mcerr << "ERROR in ControlParam::ControlParam(...):\n";
628 mcerr << "s_ban_sub is outside limits, s_ban_sub=" << fs_ban_sub
629 << '\n';
630 spexit(mcerr);
631 }
632 if (fs_ban_cop < 0 || fs_ban_cop > 2) {
633 mcerr << "ERROR in ControlParam::ControlParam(...):\n";
634 mcerr << "s_ban_cop is outside limits, s_ban_cop=" << fs_ban_cop
635 << '\n';
636 spexit(mcerr);
637 }
638#ifdef USE_DELETE_AT_ZERO_COUNT
639 if (!(s_allow_del_at_zero_count == 0 || s_allow_del_at_zero_count == 1)) {
640 mcerr << "ERROR in ControlParam::ControlParam(...)\n";
641 mcerr << "s_allow_del_at_zero_count is outside limits, "
642 "s_allow_del_at_zero_count=" << fs_allow_del_at_zero_count
643 << '\n';
644 spexit(mcerr);
645 }
646#endif
647 }
648 }; // the total 6 bits
649#endif // ifdef USE_BIT_FIELDS
650
651 inline RegPassivePtr(void)
652 :
653#ifdef USE_BIT_OPERA
654 control_word(0),
655#elif defined USE_BIT_FIELDS
656 conparam(),
657#else
658 s_ban_del(0),
659 s_ban_sub(0),
660 s_ban_cop(0),
662 s_allow_del_at_zero_count(0),
663#endif
664#endif
665 cpp(NULL) {
666 }
667#ifdef USE_CHAR_GETSETTERS_PARAMETERS
668 inline RegPassivePtr(char fs_ban_del, char fs_ban_sub, char fs_ban_cop = 0)
669 :
670#else
671 inline RegPassivePtr(int fs_ban_del, int fs_ban_sub, int fs_ban_cop = 0)
672 :
673#endif
674#ifdef USE_BIT_OPERA
675 control_word(0),
676#elif defined(USE_BIT_FIELDS)
677 conparam(fs_ban_del, fs_ban_sub, fs_ban_cop),
678#else
679 s_ban_del(fs_ban_del), s_ban_sub(fs_ban_sub), s_ban_cop(fs_ban_cop),
681 s_allow_del_at_zero_count(0),
682#endif
683#endif
684 cpp(NULL) {
685#ifdef USE_BIT_OPERA
686 set_s_ban_del(fs_ban_del);
687 set_s_ban_sub(fs_ban_sub);
688 set_s_ban_cop(fs_ban_cop);
689#endif
690 }
691
693
695 // Copies s_ban_del and s_ban_sub
696 // Also calls clear_pointers if s_ban_sub==1 or
697 // spexit() if s_ban_sub==2 and the alist_of_prot_pointers is not empty.
698
699 inline CountPP_ns::CountPassivePtr* book(void) const {
700 if (!cpp) cpp = new CountPP_ns::CountPassivePtr(this);
701 cpp->book();
702 return cpp;
703 }
704
705 inline void clear_pointers(void) const {
706 // all pointers addressing this are cleared;
707 if (cpp) cpp->change_rpp(NULL);
708 }
709
710 virtual RegPassivePtr* copy() const { return new RegPassivePtr(*this); }
711
712 virtual ~RegPassivePtr();
713 // If there are pointers addressed this object and s_ban_del = 1,
714 // the program is terminated with output message to mcerr.
715 // Otherwise (normal behaviour) the references are cleared.
716
717 virtual void print(std::ostream& file, int l = 1) const;
718 friend std::ostream& operator<<(std::ostream& file, const RegPassivePtr& f);
719
720// Three parameters controlling behaviour of pointee object at
721// its deletion and substitution.
722// They are included for the sake of flexibility and
723// they are necessary very rarely. Normally they are not used.
724// If needed, you can set them though constructors,
725// or change responsibly directly.
726// Obviously, this is a temporary design.
727// It needs then to pack all these small numbers in one computer word.
728
729#ifdef USE_BIT_OPERA
730 private:
731 unsigned char control_word;
732
733 public:
734#ifdef USE_PRIVATE_PARAM_IN_PASSIVEPTR
735 private:
736#endif
737 static int s_ban_del_ignore;
738 static int s_print_adr_cpp;
739#ifdef USE_PRIVATE_PARAM_IN_PASSIVEPTR
740 public:
741#endif
742
743#elif defined(USE_BIT_FIELDS)
744 private:
745 ControlParam conparam;
746
747 public:
748#ifdef USE_PRIVATE_PARAM_IN_PASSIVEPTR
749 private:
750#endif
751 static int s_ban_del_ignore;
752 static int s_print_adr_cpp;
753#ifdef USE_PRIVATE_PARAM_IN_PASSIVEPTR
754 public:
755#endif
756
757#else // for elif defined( USE_BIT_FIELDS )
758
759#ifdef USE_PRIVATE_PARAM_IN_PASSIVEPTR
760 private:
761#endif
762#ifdef USE_CHAR_CONTROL_VARIABLES
763 char s_ban_del;
764#else
765 int s_ban_del;
766#endif
767 // sign whether this object can (0) or cannot (1)
768 // be deleted if it is addressed.
769 // Normally it can. When it happens, the pointers addressing this object
770 // are cleared and set to NULL.
771 // If user needs to find where he deletes referenced object,
772 // he may assign this variable to 1
773
774 static int s_ban_del_ignore;
775// auxiliary variable with default value 0,
776// meaning that s_ban_del is not ignored.
777// In the case of value 1 s_ban_del is ignored, whatever it is.
778// It is used in RegPassivePtr::~RegPassivePtr() to avoid loops at exiting
779// after the fist deletion of referenced object at s_ban_del = 1 is found.
780
781#ifdef USE_CHAR_CONTROL_VARIABLES
782 char s_ban_sub;
783#else
784 int s_ban_sub;
785#endif
786// sign controlling substitution of addressed object:
787// 0 - it can be substituted and the pointers addressing "this" preserve
788// their values (normal default case).
789// 1 - it can be substituted, but the pointers will be assigned NULL.
790// In the case of self-assignment and valid pointers to "this"
791// the run-time error is triggered, because otherwise either
792// the pointers to copied object would not be preserved or
793// the pointers to "this" would not be cleared - principal contradiction.
794// 2 - it cannot be substituted, if there are pointers to "this",
795// attempt to substitute in this case triggers error.
796// In the case of absence of pointers to this it is substituted.
797// Note: if the substitution is allowed,
798// s_ban_del, s_ban_sub, and s_ban_cop are themselves substituted -
799// arbitrary decision, perhaps correct.
800
801#ifdef USE_CHAR_CONTROL_VARIABLES
802 char s_ban_cop;
803#else
804 int s_ban_cop;
805#endif
806// sign controlling copying addressed object
807// 0 - it can always be copied
808// 1 - it can be copied only if there are no references,
809// otherwise it will be runtime error.
810// 2 - it can never be copied, but it is anyway runtime error,
811// the compiler cannot detect it.
812
813#ifdef USE_DELETE_AT_ZERO_COUNT
814#ifdef USE_CHAR_CONTROL_VARIABLES
815 char s_allow_del_at_zero_count;
816#else
817 int s_allow_del_at_zero_count;
818#endif
819// concession to people who likes shared pointers.
820// Instructs PassivePtr::~PassivePtr to delete the object if that
821// pointer is last. Think twice before use.
822// It basically violates the ideoma of reference to independent object.
823// Also in the case of circular references the program can fall into loop
824// of destructors, which is not the case for regular passive pointers.
825#endif
826
827 static int s_print_adr_cpp;
828// signature to print the address of cpp in operator<<
829// by default it is 0 and address is not printed,
830// but only the remark that it is NULL or not NULL is printed.
831// It is good for making such output listings which do not depend
832// on computer and can be automatically compared.
833// But in the case of some deep debug the user can make them printed
834// if he assigns s_print_adr_cpp = 1.
835#ifdef USE_PRIVATE_PARAM_IN_PASSIVEPTR
836 public:
837#endif
838
839#endif // for elif defined( USE_BIT_FIELDS )
840
841#ifdef USE_GETSETTERS_IN_PASSIVEPTR
842 public:
843#ifdef USE_CHAR_GETSETTERS_PARAMETERS
844 inline void set_s_ban_del(char fs_ban_del)
845#else
846 inline void set_s_ban_del(int fs_ban_del)
847#endif
848 {
849#ifdef USE_BIT_OPERA
850 if (fs_ban_del == 0)
851 clear_bit(control_word, eb_s_ban_del);
852 else if (fs_ban_del == 1)
853 rise_bit(control_word, eb_s_ban_del);
854#else
855 if (fs_ban_del == 0 || fs_ban_del == 1) {
856#ifdef USE_BIT_FIELDS
857 conparam.s_ban_del = fs_ban_del;
858#else
859 s_ban_del = fs_ban_del;
860#endif
861 }
862#endif
863 else {
864 mcerr << "ERROR in inline void set_s_ban_del(int fs_ban_del):\n";
865 mcerr << "s_ban_del is outside limits, s_ban_del=" << int(fs_ban_del)
866 << '\n';
867 spexit(mcerr);
868 }
869 }
870
871#ifdef USE_CHAR_GETSETTERS_PARAMETERS
872 inline char get_s_ban_del(void) const
873#else
874 inline int get_s_ban_del(void) const
875#endif
876#ifdef USE_BIT_OPERA
877 {
878 if ((control_word & eb_s_ban_del) != 0)
879 return 1;
880 else
881 return 0;
882 }
883#elif defined(USE_BIT_FIELDS)
884 {
885 return conparam.s_ban_del;
886 }
887#else
888 { return s_ban_del; }
889#endif
890
891#ifdef USE_CHAR_GETSETTERS_PARAMETERS
892 inline static void set_s_ban_del_ignore(char fs_ban_del_ignore)
893#else
894 inline static void set_s_ban_del_ignore(int fs_ban_del_ignore)
895#endif
896 {
897 if (fs_ban_del_ignore == 0 || fs_ban_del_ignore == 1) {
898 s_ban_del_ignore = fs_ban_del_ignore;
899 } else {
900 mcerr << "ERROR in inline void set_s_ban_del_ignore(int "
901 "fs_ban_del_ignore ):\n";
902 mcerr << "s_ban_del_ignore is outside limits, s_ban_del_ignore="
903 << int(fs_ban_del_ignore) << '\n';
904 spexit(mcerr);
905 }
906 }
907
908#ifdef USE_CHAR_GETSETTERS_PARAMETERS
909 inline static char get_s_ban_del_ignore(void)
910#else
911 inline static int get_s_ban_del_ignore(void)
912#endif
913 {
914 return s_ban_del_ignore;
915 }
916
917#ifdef USE_CHAR_GETSETTERS_PARAMETERS
918 inline void set_s_ban_sub(char fs_ban_sub)
919#else
920 inline void set_s_ban_sub(int fs_ban_sub)
921#endif
922 {
923#ifdef USE_BIT_OPERA
924 if (fs_ban_sub == 0) {
925 clear_bit(control_word, eb_s_ban_sub1);
926 clear_bit(control_word, eb_s_ban_sub2);
927 } else if (fs_ban_sub == 1) {
928 rise_bit(control_word, eb_s_ban_sub1);
929 clear_bit(control_word, eb_s_ban_sub2);
930 } else if (fs_ban_sub == 2) {
931 clear_bit(control_word, eb_s_ban_sub1);
932 rise_bit(control_word, eb_s_ban_sub2);
933 }
934#else
935 if (fs_ban_sub >= 0 && fs_ban_sub <= 2) {
936#ifdef USE_BIT_FIELDS
937 conparam.s_ban_sub = fs_ban_sub;
938#else
939 s_ban_sub = fs_ban_sub;
940#endif
941 }
942#endif
943 else {
944 mcerr << "ERROR in inline void set_s_ban_sub(int fs_ban_sub):\n";
945 mcerr << "s_ban_sub is outside limits, s_ban_sub=" << int(fs_ban_sub)
946 << '\n';
947 spexit(mcerr);
948 }
949 }
950
951#ifdef USE_CHAR_GETSETTERS_PARAMETERS
952 inline char get_s_ban_sub(void) const
953#else
954 inline int get_s_ban_sub(void) const
955#endif
956#ifdef USE_BIT_OPERA
957 {
958 if ((control_word & eb_s_ban_sub2) == 0) {
959 if ((control_word & eb_s_ban_sub1) == 0)
960 return 0;
961 else
962 return 1;
963 } else {
964 // Iprintn(mcout, (control_word & eb_s_ban_sub1) );
965 // Iprintn(mcout, (control_word & eb_s_ban_sub2) );
966 return 2;
967 }
968 }
969#elif defined(USE_BIT_FIELDS)
970 {
971 return conparam.s_ban_sub;
972 }
973#else
974 { return s_ban_sub; }
975#endif
976
977#ifdef USE_CHAR_GETSETTERS_PARAMETERS
978 inline void set_s_ban_cop(char fs_ban_cop)
979#else
980 inline void set_s_ban_cop(int fs_ban_cop)
981#endif
982 {
983#ifdef USE_BIT_OPERA
984 if (fs_ban_cop == 0) {
985 clear_bit(control_word, eb_s_ban_cop1);
986 clear_bit(control_word, eb_s_ban_cop2);
987 } else if (fs_ban_cop == 1) {
988 rise_bit(control_word, eb_s_ban_cop1);
989 clear_bit(control_word, eb_s_ban_cop2);
990 } else if (fs_ban_cop == 2) {
991 clear_bit(control_word, eb_s_ban_cop1);
992 rise_bit(control_word, eb_s_ban_cop2);
993 }
994#else
995 if (fs_ban_cop >= 0 && fs_ban_cop <= 2) {
996#ifdef USE_BIT_FIELDS
997 conparam.s_ban_cop = fs_ban_cop;
998#else
999 s_ban_cop = fs_ban_cop;
1000#endif
1001 }
1002#endif
1003 else {
1004 mcerr << "ERROR in inline void set_s_ban_cop(int fs_ban_cop):\n";
1005 mcerr << "s_ban_cop is outside limits, s_ban_cop=" << int(fs_ban_cop)
1006 << '\n';
1007 spexit(mcerr);
1008 }
1009 }
1010
1011#ifdef USE_CHAR_GETSETTERS_PARAMETERS
1012 inline char get_s_ban_cop(void) const
1013#else
1014 inline int get_s_ban_cop(void) const
1015#endif
1016#ifdef USE_BIT_OPERA
1017 {
1018 if ((control_word & eb_s_ban_cop2) == 0) {
1019 if ((control_word & eb_s_ban_cop1) == 0)
1020 return 0;
1021 else
1022 return 1;
1023 } else {
1024 return 2;
1025 }
1026 }
1027#elif defined USE_BIT_FIELDS
1028 {
1029 return conparam.s_ban_cop;
1030 }
1031#else
1032 { return s_ban_cop; }
1033#endif
1034
1035#ifdef USE_DELETE_AT_ZERO_COUNT
1036
1037#ifdef USE_CHAR_GETSETTERS_PARAMETERS
1038 inline void set_s_allow_del_at_zero_count(char fs_allow_del_at_zero_count)
1039#else
1040 inline void set_s_allow_del_at_zero_count(int fs_allow_del_at_zero_count)
1041#endif
1042 {
1043#ifdef USE_BIT_OPERA
1044 if (fs_allow_del_at_zero_count == 0)
1045 clear_bit(control_word, eb_s_allow_del_at_zero_count);
1046 else if (fs_allow_del_at_zero_count == 1)
1047 rise_bit(control_word, eb_s_allow_del_at_zero_count);
1048#else
1049 if (fs_allow_del_at_zero_count == 0 || fs_allow_del_at_zero_count == 1) {
1050#ifdef USE_BIT_FIELDS
1051 conparam.s_allow_del_at_zero_count = fs_allow_del_at_zero_count;
1052#else
1053 s_allow_del_at_zero_count = fs_allow_del_at_zero_count;
1054#endif
1055 }
1056#endif
1057 else {
1058 mcerr << "ERROR in inline void set_s_allow_del_at_zero_count(int "
1059 "fs_allow_del_at_zero_count):\n";
1060 mcerr << "s_allow_del_at_zero_count is outside limits, "
1061 "s_allow_del_at_zero_count=" << int(fs_allow_del_at_zero_count)
1062 << '\n';
1063 spexit(mcerr);
1064 }
1065 }
1066
1067#ifdef USE_CHAR_GETSETTERS_PARAMETERS
1068 inline char get_s_allow_del_at_zero_count(void) const
1069#else
1070 inline int get_s_allow_del_at_zero_count(void) const
1071#endif
1072#ifdef USE_BIT_OPERA
1073 {
1074 if ((control_word & eb_s_allow_del_at_zero_count) != 0)
1075 return 1;
1076 else
1077 return 0;
1078 }
1079#elif defined(USE_BIT_FIELDS)
1080 {
1081 return conparam.s_allow_del_at_zero_count;
1082 }
1083#else
1084 { return s_allow_del_at_zero_count; }
1085#endif
1086
1087#endif // for ifdef USE_DELETE_AT_ZERO_COUNT
1088
1089#ifdef USE_CHAR_GETSETTERS_PARAMETERS
1090 inline static void set_s_print_adr_cpp(char fs_print_adr_cpp)
1091#else
1092 inline static void set_s_print_adr_cpp(int fs_print_adr_cpp)
1093#endif
1094 {
1095 if (fs_print_adr_cpp == 0 || fs_print_adr_cpp == 1) {
1096 s_print_adr_cpp = fs_print_adr_cpp;
1097 } else {
1098 mcerr << "ERROR in inline void set_s_print_adr_cpp(int fs_print_adr_cpp "
1099 "):\n";
1100 mcerr << "s_print_adr_cpp is outside limits, s_print_adr_cpp="
1101 << int(fs_print_adr_cpp) << '\n';
1102 spexit(mcerr);
1103 }
1104 }
1105
1106#ifdef USE_CHAR_GETSETTERS_PARAMETERS
1107 inline static char get_s_print_adr_cpp(void)
1108#else
1109 inline static int get_s_print_adr_cpp(void)
1110#endif
1111 {
1112 return s_print_adr_cpp;
1113 }
1114
1115#endif // for ifdef USE_GETSETTERS_IN_PASSIVEPTR
1116
1117 long get_total_number_of_references(void) const;
1118
1119 private:
1120 mutable CountPP_ns::CountPassivePtr* cpp; // reference to counter class
1121};
1122
1124 if (number_of_booked != 0) {
1125 mcerr << "Error in CountPassivePtr::~CountPassivePtr():\n"
1126 << " number_of_booked != 0, number_of_booked=" << number_of_booked
1127 << '\n';
1128 if (rpp != NULL)
1129 mcerr << (*rpp);
1130 else
1131 mcerr << "rpp = NULL\n";
1132 spexit(mcerr);
1133 }
1134 if (rpp != NULL) rpp->cpp = NULL;
1135}
1136
1137template <class X>
1139 public:
1140 friend class RegPassivePtr;
1141
1142 inline X* get(void) const {
1143 if (cpp == NULL) return NULL;
1144#ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1145
1146 if (cpp->get_rpp() == NULL) return NULL;
1147#ifdef USE_CHECK_DOUBLE_PTR_IN_PASSIVEPTR
1148 X* temp_ptr = dynamic_cast<X*>(const_cast<RegPassivePtr*>(cpp->get_rpp()));
1149 if (ptr != temp_ptr) {
1150 mcerr << "Error in inline X* PassivePtr::get(void):\n";
1151 mcerr << "ptr != temp_ptr\n";
1152 spexit(mcerr);
1153 }
1154#endif
1155 return ptr;
1156#else // for ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1157 else
1158 return (X*)(cpp->get_rpp());
1159#endif // for ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1160 }
1161
1162 // Since the pointer is passive, there is no cloning and pass and put
1163 // make the same job.
1164 // 03.06.2006: commenting off pass in order to forbid
1165 // correct for active pointer but
1166 // erroneous for passive pointer statements like ptr.pass(new any_class).
1167 // inline void pass(const X* fptr) {put( fptr );}
1168
1169 inline void put(X* fptr); // unregirster old registered object and
1170 // pass fptr to this.
1171
1172 // void print(std::ostream& file, int l) const
1173 // { if(ptr!=NULL) ptr->print(file, l); }
1174 inline PassivePtr(void)
1175 : cpp(NULL)
1177 ,
1178 ptr(NULL)
1179#endif
1180 {
1181 }
1182 inline PassivePtr(X* fptr) {
1183 if (fptr != NULL)
1184 cpp = fptr->book();
1185 else
1186 cpp = NULL;
1187#ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1188 ptr = fptr;
1189#endif
1190 }
1191 inline PassivePtr(X& fptr) {
1192 cpp = fptr.book();
1193#ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1194 ptr = &fptr;
1195#endif
1196 }
1197
1198 inline PassivePtr(const PassivePtr<X>& f);
1199
1202
1203 // Y may be any derived class from X
1204 template <class Y>
1205 PassivePtr<X>(const PassivePtr<Y>& f);
1207 // get the pointer from f, clear f,
1208 // put the pointer to this->ptr
1209 // and register it. Thus, the pointer is passed from f to this.
1210
1211 inline X* operator->(void) const;
1212 inline X& operator*(void) const;
1213 inline X* getver(void) const;
1214#ifdef IMPLICIT_X_STAR
1215 inline operator X*(void) const;
1216#endif
1218 if (cpp == NULL)
1219 return 0;
1220 else
1221 return cpp->get_number_of_booked();
1222 }
1223 void print(std::ostream& file, int l = 1) const;
1224 virtual PassivePtr* copy() const { return new PassivePtr(*this); }
1225 virtual ~PassivePtr();
1226
1227 private:
1229#ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1230 X* ptr;
1231#endif
1232};
1233
1234template <class X>
1235template <class Y>
1237 : cpp(NULL) {
1238 put((f.get()));
1239}
1240
1241template <class X>
1242void PassivePtr<X>::print(std::ostream& file, int l) const {
1243 Ifile << "PassivePtr<X>:";
1244 if (get() == NULL)
1245 file << " pointer is NULL, no object, number of ref's is "
1246 << get_total_number_of_references() << "\n";
1247 else {
1248 file << noindent;
1249 get()->print(file, l);
1250 file << yesindent;
1251 indn.n += 2;
1252 Ifile << "number of ref's is " << get_total_number_of_references() << '\n';
1253 indn.n -= 2;
1254 }
1255}
1256template <class X>
1257std::ostream& operator<<(std::ostream& file, const PassivePtr<X>& f) {
1258 Ifile << "PassivePtr<X>:";
1259 if (f.get() == NULL)
1260 file << " pointer is NULL, no object, number of ref's is "
1261 << f.get_total_number_of_references() << "\n";
1262 else {
1263 file << noindent;
1264 file << (*f.get());
1265 file << yesindent;
1266 indn.n += 2;
1267 Ifile << "number of ref's is " << f.get_total_number_of_references()
1268 << '\n';
1269 indn.n -= 2;
1270 }
1271 return file;
1272}
1273
1274template <class X>
1275inline void PassivePtr<X>::put(X* fptr) {
1276 // unregister old registered object and pass fptr to this.
1277 if (cpp != NULL) {
1278#ifdef USE_DELETE_AT_ZERO_COUNT
1279 const RegPassivePtr* arptr;
1280 if ((arptr = cpp->get_rpp()) != NULL &&
1282 arptr->get_s_allow_del_at_zero_count() == 1 &&
1283#else
1284 arptr->s_allow_del_at_zero_count == 1 &&
1285#endif
1286 cpp->get_number_of_booked() == 1)
1287 delete arptr;
1288// fptr should not be part of old object!
1289#endif
1290 cpp->unbook();
1291 if (cpp->get_rpp() == NULL && cpp->get_number_of_booked() == 0)
1292 // there is no referred object and no other references
1293 delete cpp;
1294 }
1295 if (fptr != NULL)
1296 cpp = fptr->book();
1297 else
1298 cpp = NULL;
1299#ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1300 ptr = fptr;
1301#endif
1302}
1303
1304template <class X>
1306 if (f.cpp != NULL) {
1307 f.cpp->book();
1308 cpp = f.cpp;
1309 } else
1310 cpp = NULL;
1311#ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1312 ptr = f.ptr;
1313#endif
1314}
1315template <class X>
1317 if (this != &f) put(f.get());
1318 return *this;
1319}
1320
1321template <class X>
1323 put(f);
1324 return *this;
1325}
1326
1327template <class X>
1329 if (cpp != NULL) {
1330#ifdef USE_DELETE_AT_ZERO_COUNT
1331 const RegPassivePtr* arptr;
1332 if ((arptr = cpp->get_rpp()) != NULL &&
1334 arptr->get_s_allow_del_at_zero_count() == 1 &&
1335#else
1336 arptr->s_allow_del_at_zero_count == 1 &&
1337#endif
1338 cpp->get_number_of_booked() == 1)
1339 delete arptr;
1340// fptr should not be part of old object!
1341#endif
1342 cpp->unbook();
1343 if (cpp->get_rpp() == NULL && cpp->get_number_of_booked() == 0) {
1344 delete cpp;
1345 cpp = NULL;
1346 }
1347 }
1348 cpp = f.cpp;
1349 if (cpp != NULL) cpp->book();
1350#ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1351 ptr = f.ptr;
1352#endif
1353 f.put(NULL);
1354}
1355
1356template <class X>
1357inline X* PassivePtr<X>::operator->(void) const {
1358#ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1359#ifdef SKIP_CHECKS_NULL
1360 return ptr;
1361#else
1362 if (cpp == NULL) {
1363 mcerr << "Error in X* PassivePtr<X>::operator->(void) const: cpp == NULL\n";
1364 mcerr << "This means that the pointer is emtpy, "
1365 << "there is no addressed object.\n";
1366 mcerr << "Type of X is (in internal notations) " << typeid(X).name()
1367 << '\n';
1368 spexit(mcerr);
1369 }
1370 if (cpp->get_rpp() == NULL) {
1371 mcerr << "Error in X* PassivePtr<X>::operator->(void) const: "
1372 "cpp->get_rpp() == NULL\n";
1373 mcerr << "This means that the pointer is emtpy, "
1374 << "there is no addressed object.\n";
1375 mcerr << "Type of X is (in internal notations) " << typeid(X).name()
1376 << '\n';
1377 spexit(mcerr);
1378 }
1379#ifdef USE_CHECK_DOUBLE_PTR_IN_PASSIVEPTR
1380 X* temp_ptr = dynamic_cast<X*>(const_cast<RegPassivePtr*>(cpp->get_rpp()));
1381 if (ptr != temp_ptr) {
1382 mcerr << "Error in inline X* PassivePtr::operator->(void):\n";
1383 mcerr << "ptr != temp_ptr\n";
1384 spexit(mcerr);
1385 }
1386#endif
1387 return ptr;
1388#endif // for ifdef SKIP_CHECKS_NULL
1389#else // for ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1390#ifdef SKIP_CHECKS_NULL
1391 const RegPassivePtr* rpp = cpp->get_rpp();
1392#else
1393 if (cpp == NULL) {
1394 mcerr << "Error in X* PassivePtr<X>::operator->(void) const: cpp == NULL\n";
1395 mcerr << "This means that the pointer is emtpy, "
1396 << "there is no addressed object.\n";
1397 mcerr << "Type of X is (in internal notations) " << typeid(X).name()
1398 << '\n';
1399 spexit(mcerr);
1400 }
1401 const RegPassivePtr* rpp;
1402 if ((rpp = cpp->get_rpp()) == NULL) {
1403 mcerr << "Error in X* PassivePtr<X>::operator->(void) const: "
1404 "cpp->get_rpp() == NULL\n";
1405 mcerr << "This means that the pointer is emtpy, "
1406 << "there is no addressed object.\n";
1407 mcerr << "Type of X is (in internal notations) " << typeid(X).name()
1408 << '\n';
1409 spexit(mcerr);
1410 }
1411#endif
1412 return (X*)(rpp);
1413#endif // for ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1414}
1415
1416template <class X>
1417inline X& PassivePtr<X>::operator*(void) const {
1418#ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1419#ifdef SKIP_CHECKS_NULL
1420 return *ptr;
1421#else
1422 if (cpp == NULL) {
1423 mcerr << "Error in X& PassivePtr<X>::operator*(void) const: cpp == NULL\n";
1424 mcerr << "This means that the pointer is emtpy, "
1425 << "there is no addressed object.\n";
1426 mcerr << "Type of X is (in internal notations) " << typeid(X).name()
1427 << '\n';
1428 spexit(mcerr);
1429 }
1430 if (cpp->get_rpp() == NULL) {
1431 mcerr << "Error in X& PassivePtr<X>::operator*(void) const: cpp->get_rpp() "
1432 "== NULL\n";
1433 mcerr << "This means that the pointer is emtpy, "
1434 << "there is no addressed object.\n";
1435 mcerr << "Type of X is (in internal notations) " << typeid(X).name()
1436 << '\n';
1437 spexit(mcerr);
1438 }
1439#ifdef USE_CHECK_DOUBLE_PTR_IN_PASSIVEPTR
1440 X* temp_ptr = dynamic_cast<X*>(const_cast<RegPassivePtr*>(cpp->get_rpp()));
1441 if (ptr != temp_ptr) {
1442 mcerr << "Error in inline X& PassivePtr::operator*(void):\n";
1443 mcerr << "ptr != temp_ptr\n";
1444 spexit(mcerr);
1445 }
1446#endif
1447 return *ptr;
1448#endif // for ifdef SKIP_CHECKS_NULL
1449#else // for ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1450#ifdef SKIP_CHECKS_NULL
1451 static const RegPassivePtr* rpp = cpp->get_rpp();
1452#else
1453 if (cpp == NULL) {
1454 mcerr << "Error in X& PassivePtr<X>::operator*(void) const: cpp == NULL\n";
1455 mcerr << "This means that the pointer is emtpy, "
1456 << "there is no addressed object.\n";
1457 mcerr << "Type of X is (in internal notations) " << typeid(X).name()
1458 << '\n';
1459 spexit(mcerr);
1460 }
1461 static const RegPassivePtr* rpp;
1462 // I have put static here only to avoid
1463 // perhaps erroneous warning which appear
1464 // in compiler : gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
1465 // This is old compiler. At newer ones there is no problems.
1466 // The message is
1467 // AbsPtr.h:997: warning: reference to local variable `rpp' returned
1468 // This is in fact wrong statement, but so as not to make users thinking
1469 // about it, I made this variable static.
1470
1471 if ((rpp = cpp->get_rpp()) == NULL) {
1472 mcerr << "Error in X& PassivePtr<X>::operator*(void) const: cpp->get_rpp() "
1473 "== NULL\n";
1474 mcerr << "This means that the pointer is emtpy, "
1475 << "there is no addressed object.\n";
1476 mcerr << "Type of X is (in internal notations) " << typeid(X).name()
1477 << '\n';
1478 spexit(mcerr);
1479 }
1480#endif
1481 return *((X*)(rpp));
1482#endif // for ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1483}
1484
1485template <class X>
1486inline X* PassivePtr<X>::getver(void) const {
1487#ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1488#ifdef SKIP_CHECKS_NULL
1489 return ptr;
1490#else
1491 if (cpp == NULL) {
1492 mcerr << "Error in X* PassivePtr<X>::getver(void) const: cpp == NULL\n";
1493 mcerr << "This means that the pointer is emtpy, "
1494 << "there is no addressed object.\n";
1495 mcerr << "Type of X is (in internal notations) " << typeid(X).name()
1496 << '\n';
1497 spexit(mcerr);
1498 }
1499 if (cpp->get_rpp() == NULL) {
1500 mcerr << "Error in X* PassivePtr<X>::getver(void) const: cpp->get_rpp() == "
1501 "NULL\n";
1502 mcerr << "This means that the pointer is emtpy, "
1503 << "there is no addressed object.\n";
1504 mcerr << "Type of X is (in internal notations) " << typeid(X).name()
1505 << '\n';
1506 spexit(mcerr);
1507 }
1508#ifdef USE_CHECK_DOUBLE_PTR_IN_PASSIVEPTR
1509 X* temp_ptr = dynamic_cast<X*>(const_cast<RegPassivePtr*>(cpp->get_rpp()));
1510 if (ptr != temp_ptr) {
1511 mcerr << "Error in inline X* PassivePtr::getver(void):\n";
1512 mcerr << "ptr != temp_ptr\n";
1513 spexit(mcerr);
1514 }
1515#endif
1516 return ptr;
1517#endif // for ifdef SKIP_CHECKS_NULL
1518#else // for ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1519#ifdef SKIP_CHECKS_NULL
1520 const RegPassivePtr* rpp = cpp->get_rpp();
1521#else
1522 if (cpp == NULL) {
1523 mcerr << "Error in X* PassivePtr<X>::getver(void) const: cpp == NULL\n";
1524 mcerr << "This means that the pointer is emtpy, "
1525 << "there is no addressed object.\n";
1526 mcerr << "Type of X is (in internal notations) " << typeid(X).name()
1527 << '\n';
1528 spexit(mcerr);
1529 }
1530 const RegPassivePtr* rpp;
1531 if ((rpp = cpp->get_rpp()) == NULL) {
1532 mcerr << "Error in X* PassivePtr<X>::getver(void) const: cpp->get_rpp() == "
1533 "NULL\n";
1534 mcerr << "This means that the pointer is emtpy, "
1535 << "there is no addressed object.\n";
1536 mcerr << "Type of X is (in internal notations) " << typeid(X).name()
1537 << '\n';
1538 spexit(mcerr);
1539 }
1540#endif
1541 return (X*)(rpp);
1542#endif // for ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1543}
1544
1545#ifdef IMPLICIT_X_STAR
1546template <class X>
1547inline PassivePtr<X>::operator X*(void) const {
1548#ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1549#ifdef SKIP_CHECKS_NULL
1550 return ptr;
1551#else
1552 if (cpp == NULL) {
1553 mcerr << "Error in PassivePtr<X>::operator X*(void) const: cpp == NULL\n";
1554 mcerr << "This means that the pointer is emtpy, "
1555 << "there is no addressed object.\n";
1556 mcerr << "Type of X is (in internal notations) " << typeid(X).name()
1557 << '\n';
1558 spexit(mcerr);
1559 }
1560 if (cpp->get_rpp() == NULL) {
1561 mcerr << "Error in X* PassivePtr<X>::operator X*(void) const: "
1562 "cpp->get_rpp() == NULL\n";
1563 mcerr << "This means that the pointer is emtpy, "
1564 << "there is no addressed object.\n";
1565 mcerr << "Type of X is (in internal notations) " << typeid(X).name()
1566 << '\n';
1567 spexit(mcerr);
1568 }
1569#ifdef USE_CHECK_DOUBLE_PTR_IN_PASSIVEPTR
1570 X* temp_ptr = dynamic_cast<X*>(const_cast<RegPassivePtr*>(cpp->get_rpp()));
1571 if (ptr != temp_ptr) {
1572 mcerr << "Error in inline X* PassivePtr::operator X*(void):\n";
1573 mcerr << "ptr != temp_ptr\n";
1574 spexit(mcerr);
1575 }
1576#endif
1577 return ptr;
1578#endif // for ifdef SKIP_CHECKS_NULL
1579#else // for ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1580#ifdef SKIP_CHECKS_NULL
1581 const RegPassivePtr* rpp = cpp->get_rpp();
1582#else
1583 if (cpp == NULL) {
1584 mcerr
1585 << "Error in X* PassivePtr<X>::operator X*(void) const: cpp == NULL\n";
1586 mcerr << "This means that the pointer is emtpy, "
1587 << "there is no addressed object.\n";
1588 mcerr << "Type of X is (in internal notations) " << typeid(X).name()
1589 << '\n';
1590 spexit(mcerr);
1591 }
1592 const RegPassivePtr* rpp;
1593 if ((rpp = cpp->get_rpp()) == NULL) {
1594 mcerr << "Error in X* PassivePtr<X>::operator X*(void) const: "
1595 "cpp->get_rpp() == NULL\n";
1596 mcerr << "This means that the pointer is emtpy, "
1597 << "there is no addressed object.\n";
1598 mcerr << "Type of X is (in internal notations) " << typeid(X).name()
1599 << '\n';
1600 spexit(mcerr);
1601 }
1602#endif
1603 return (X*)(rpp);
1604#endif // for ifdef USE_DOUBLE_PTR_IN_PASSIVEPTR
1605}
1606#endif
1607template <class X>
1608inline int operator==(const PassivePtr<X>& f1, const PassivePtr<X>& f2) {
1609 // comparison of addresses, so it mimics regular pointers
1610 return f1.get() == f2.get();
1611}
1612
1613template <class X>
1615 if (cpp) {
1616#ifdef USE_DELETE_AT_ZERO_COUNT
1617 const RegPassivePtr* arptr;
1618 if ((arptr = cpp->get_rpp()) != NULL &&
1620 arptr->get_s_allow_del_at_zero_count() == 1 &&
1621#else
1622 arptr->s_allow_del_at_zero_count == 1 &&
1623#endif
1624 cpp->get_number_of_booked() == 1)
1625 delete arptr;
1626#endif
1627 cpp->unbook();
1628 // mcout<<"PassivePtr<X>::~PassivePtr(): &ptr="<<&ptr<<" *ptr="<<*ptr<<'\n';
1629 if (cpp->get_rpp() == NULL && cpp->get_number_of_booked() == 0) {
1630 delete cpp;
1631 cpp = NULL;
1632 }
1633 }
1634}
1635
1636template <class X>
1638 // necessary for std::set
1639 return f1.get() < f2.get();
1640}
1641
1642}
1643
1644#endif
#define USE_PRIVATE_PARAM_IN_PASSIVEPTR
Definition: AbsPtr.h:76
#define USE_DOUBLE_PTR_IN_PASSIVEPTR
Definition: AbsPtr.h:23
#define USE_DELETE_AT_ZERO_COUNT
Definition: AbsPtr.h:33
#define spexit(stream)
Definition: FunNameStack.h:256
Active pointer or automatic container or controlling pointer.
Definition: AbsPtr.h:199
void print(std::ostream &file, int l=1) const
Definition: AbsPtr.h:391
void clear(void)
Definition: AbsPtr.h:281
ActivePtr(const ActivePtr< X, C > &f, Pilfer)
Definition: AbsPtr.h:346
virtual ~ActivePtr()
Definition: AbsPtr.h:366
X * getver(void) const
Definition: AbsPtr.h:465
X & operator*(void) const
Definition: AbsPtr.h:452
ActivePtr(void)
Definition: AbsPtr.h:317
void put(const X *fptr)
Definition: AbsPtr.h:225
X * get(void) const
Definition: AbsPtr.h:215
void pass(X *fptr)
Definition: AbsPtr.h:247
ActivePtr(const X *fptr, Clone)
Definition: AbsPtr.h:319
ActivePtr(const ActivePtr< X, C > &f)
Definition: AbsPtr.h:334
X * extract(void)
Definition: AbsPtr.h:276
void pilfer(const ActivePtr< X, C > &f)
Definition: AbsPtr.h:291
X * operator->(void) const
Definition: AbsPtr.h:438
ActivePtr(X *fptr, Pass)
Definition: AbsPtr.h:355
virtual ActivePtr * copy() const
Definition: AbsPtr.h:365
ActivePtr & operator=(const ActivePtr< X, C > &f)
Definition: AbsPtr.h:357
Counter of protected pointers.
Definition: AbsPtr.h:506
void change_rpp(const RegPassivePtr *frpp)
Definition: AbsPtr.h:516
const RegPassivePtr * get_rpp(void)
Definition: AbsPtr.h:515
CountPassivePtr(const RegPassivePtr *frpp)
Definition: AbsPtr.h:508
PassivePtr(X &fptr)
Definition: AbsPtr.h:1191
X * operator->(void) const
Definition: AbsPtr.h:1357
X * getver(void) const
Definition: AbsPtr.h:1486
X * get(void) const
Definition: AbsPtr.h:1142
PassivePtr(void)
Definition: AbsPtr.h:1174
PassivePtr< X > & operator=(X *f)
Definition: AbsPtr.h:1322
void move_pointer(PassivePtr< X > &f)
Definition: AbsPtr.h:1328
long get_total_number_of_references(void) const
Definition: AbsPtr.h:1217
void put(X *fptr)
Definition: AbsPtr.h:1275
PassivePtr< X > & operator=(const PassivePtr< X > &f)
Definition: AbsPtr.h:1316
PassivePtr(X *fptr)
Definition: AbsPtr.h:1182
PassivePtr(const PassivePtr< X > &f)
Definition: AbsPtr.h:1305
void print(std::ostream &file, int l=1) const
Definition: AbsPtr.h:1242
X & operator*(void) const
Definition: AbsPtr.h:1417
virtual ~PassivePtr()
Definition: AbsPtr.h:1614
virtual PassivePtr * copy() const
Definition: AbsPtr.h:1224
static char get_s_ban_del_ignore(void)
Definition: AbsPtr.h:909
void clear_pointers(void) const
Definition: AbsPtr.h:705
static void set_s_ban_del_ignore(char fs_ban_del_ignore)
Definition: AbsPtr.h:892
static void set_s_print_adr_cpp(char fs_print_adr_cpp)
Definition: AbsPtr.h:1090
virtual ~RegPassivePtr()
Definition: AbsPtr.cpp:231
virtual void print(std::ostream &file, int l=1) const
Definition: AbsPtr.cpp:152
static char get_s_print_adr_cpp(void)
Definition: AbsPtr.h:1107
RegPassivePtr & operator=(const RegPassivePtr &f)
Definition: AbsPtr.cpp:60
char get_s_allow_del_at_zero_count(void) const
Definition: AbsPtr.h:1068
void set_s_ban_cop(char fs_ban_cop)
Definition: AbsPtr.h:978
RegPassivePtr(char fs_ban_del, char fs_ban_sub, char fs_ban_cop=0)
Definition: AbsPtr.h:668
void set_s_allow_del_at_zero_count(char fs_allow_del_at_zero_count)
Definition: AbsPtr.h:1038
char get_s_ban_sub(void) const
Definition: AbsPtr.h:952
virtual RegPassivePtr * copy() const
Definition: AbsPtr.h:710
friend std::ostream & operator<<(std::ostream &file, const RegPassivePtr &f)
Definition: AbsPtr.cpp:156
void set_s_ban_sub(char fs_ban_sub)
Definition: AbsPtr.h:918
RegPassivePtr(void)
Definition: AbsPtr.h:651
char get_s_ban_cop(void) const
Definition: AbsPtr.h:1012
void set_s_ban_del(char fs_ban_del)
Definition: AbsPtr.h:844
char get_s_ban_del(void) const
Definition: AbsPtr.h:872
CountPP_ns::CountPassivePtr * book(void) const
Definition: AbsPtr.h:699
long get_total_number_of_references(void) const
Definition: AbsPtr.cpp:222
static X * copy(const X *f)
Definition: AbsPtr.h:135
Definition: BGMesh.cpp:5
std::istream & operator>>(std::istream &file, EqualStepCoorMesh< T > &f)
Definition: tline.h:230
std::ostream & noindent(std::ostream &f)
Definition: prstream.cpp:17
void exchange(ActivePtr< X, C > &f1, ActivePtr< X, C > &f2)
Definition: AbsPtr.h:493
std::ostream & operator<<(std::ostream &file, const BGMesh &bgm)
Definition: BGMesh.cpp:36
Pilfer
Definition: AbsPtr.h:187
@ steal
Definition: AbsPtr.h:188
Clone
Definition: AbsPtr.h:190
@ do_clone
Definition: AbsPtr.h:191
int operator==(const circumf &f1, const circumf &f2)
Definition: circumf.cpp:34
Pass
Definition: AbsPtr.h:193
@ dont_clone
Definition: AbsPtr.h:194
indentation indn
Definition: prstream.cpp:15
bool operator<(PassivePtr< X > f1, PassivePtr< X > f2)
Definition: AbsPtr.h:1637
std::ostream & yesindent(std::ostream &f)
Definition: prstream.cpp:21
#define mcout
Definition: prstream.h:126
#define Ifile
Definition: prstream.h:196
#define mcerr
Definition: prstream.h:128
#define Iprintn(file, name)
Definition: prstream.h:205