Salome HOME
PR: merge from branch BR_UT_V310a2 tag BR_UT_V310a2_20051115
[modules/kernel.git] / src / Basics / BasicsGenericDestructor.hxx
1 //  SALOME Basics : general SALOME definitions and tools (C++ part - no CORBA)
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : BasicGenericDestructor.hxx
25 //  Author : Antoine YESSAYAN, Paul RASCLE, EDF
26 //  Module : SALOME
27 //  $Header$
28
29 #ifndef _BASICGENERICDESTRUCTOR_HXX_
30 #define _BASICGENERICDESTRUCTOR_HXX_
31
32 #include <list>
33 #include <algorithm>
34 #include <cassert>
35 #include <typeinfo>
36 #include <iostream>
37 #include <cstdlib>
38 #include <pthread.h>
39
40 #if defined BASICS_EXPORTS
41 #if defined WIN32
42 #define BASICS_EXPORT __declspec( dllexport )
43 #else
44 #define BASICS_EXPORT
45 #endif
46 #else
47 #if defined WNT
48 #define BASICS_EXPORT __declspec( dllimport )
49 #else
50 #define BASICS_EXPORT
51 #endif
52 #endif
53
54 //#define _DEVDEBUG_
55
56 #ifdef _DEVDEBUG_
57 #define MYDEVTRACE {std::cerr << __FILE__ << " [" << __LINE__ << "] : ";}
58 #define DEVTRACE(msg) {MYDEVTRACE; std::cerr<<msg<<std::endl<<std::flush;}
59 #else
60 #define MYDEVTRACE
61 #define DEVTRACE(msg)
62 #endif
63
64 // ============================================================================
65 /*!
66  * The PROTECTED_DELETE base class provides a protected destructor. 
67  * The only way to use PROTECTED_DELETE is inheritance:
68  *   example: class LocalTraceBufferPool : public PROTECTED_DELETE
69  * Herited class destructor must stay protected.
70  * Normal use is:
71  * - create an instance of herited class on the heap (new),
72  * - use addObj(instance) to store the instance on the static list _objList,
73  * - delete instance with deleteInstance(instance)
74  *
75  * This class is utilised with GENERIC_DESTRUCTOR and DESTRUCTOR_OF, 
76  * to program automatic deletion of objects at the end of the process, while
77  * keeping the possibility of an early destruction, if required. This is used
78  * for unit testing and trace mecanism.
79  */ 
80 // ============================================================================
81
82 class PROTECTED_DELETE
83 {
84 public:
85   static void deleteInstance(PROTECTED_DELETE *anObject);
86   static void addObj(PROTECTED_DELETE *anObject);
87
88 protected:
89   virtual ~PROTECTED_DELETE();
90   static std::list<PROTECTED_DELETE*> _objList;
91
92 private:
93   static pthread_mutex_t _listMutex;
94 };
95
96 // ============================================================================
97 /*!
98  * The GENERIC_DESTRUCTOR abstract class describes the comportement of any
99  * destruction object. This type is used to create a list of miscellaneous
100  * destruction objects.
101  *
102  * The only way to use the GENERIC_DESTRUCTOR class is inheritance:
103  *   class SPECIFIC_DESTRUCTOR : public GENERIC_DESTRUCTOR
104  * 
105  * A generic destructor provides two methods:
106  * -# a static method to add a destruction (object) to be performed:
107  *    GENERIC_DESTRUCTOR::Add(GENERIC_DESTRUCTOR &anObject);
108  *    The Destruction object is stored in a list of pointer to
109  *    GENERIC_DESTRUCTOR objects.
110  * -# an object method to execute the destruction : operator()().
111  */ 
112 // ============================================================================
113
114 class GENERIC_DESTRUCTOR
115 {
116 public :
117   BASICS_EXPORT static std::list<GENERIC_DESTRUCTOR*> *Destructors;
118
119   virtual ~GENERIC_DESTRUCTOR() {};
120   BASICS_EXPORT static const int Add(GENERIC_DESTRUCTOR &anObject);
121   BASICS_EXPORT virtual void operator()(void) = 0;
122 };
123
124 // ============================================================================
125 /*! 
126  * The DESTRUCTOR_OF class allows the user to program - at any moment - the
127  * destruction of an object at the end of the process.
128  *
129  * Example: the POINT ptrPoint will be destroyed at the end of the process
130  * (atexit).
131  *
132  * POINT *ptrPoint = new POINT ;
133  *
134  * DESTRUCTOR_OF<POINT> *ptrDestruct = new DESTRUCTOR_OF<POINT>(*ptrPoint);
135  * 
136  * Note that neither ptrPoint, nor ptrDestruct should be destroyed by the user.
137  * 
138  * The destruction object must be created dynamically because it suscribes
139  * itself in the list of destruction to be performed at the end of the process.
140  */ 
141 // ============================================================================
142
143 template <class TYPE> class DESTRUCTOR_OF : public GENERIC_DESTRUCTOR
144 {
145
146 public:
147   /*!
148     Programs the destruction at the end of the process, of the object anObject.
149     This method records in _objectPtr the address of an object to be destroyed 
150     at the end of the process
151   */
152   DESTRUCTOR_OF(TYPE &anObject):
153     _objectPtr(&anObject)
154   {
155     DEVTRACE(" DESTRUCTOR_OF " << typeid(anObject).name() 
156              << " " << _objectPtr << " " << this );
157     PROTECTED_DELETE::addObj(_objectPtr);
158     assert(GENERIC_DESTRUCTOR::Add(*this) >= 0);
159   }
160
161   /*!
162     Performs the destruction of the object.
163     This method really destroys the object pointed by _objectPtr. 
164     It should be called at the end of the process (i.e. at exit).
165   */
166   virtual void operator()(void)
167   {
168     if (_objectPtr)
169       {
170         DEVTRACE("DESTRUCTOR_OF<>::operator() " << _objectPtr);
171         if (_objectPtr) PROTECTED_DELETE::deleteInstance(_objectPtr);
172         _objectPtr = NULL;
173       }
174   }
175
176   virtual ~DESTRUCTOR_OF()
177   {
178     DEVTRACE("~DESTRUCTOR_OF() " << this);
179     assert(!_objectPtr);
180   }
181
182 private:
183   TYPE *_objectPtr;
184 };
185
186 # endif