Salome HOME
merge from branch BR_V5_DEV
[modules/kernel.git] / src / Basics / BasicsGenericDestructor.hxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  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.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  SALOME Basics : general SALOME definitions and tools (C++ part - no CORBA)
23 //  File   : BasicGenericDestructor.hxx
24 //  Author : Antoine YESSAYAN, Paul RASCLE, EDF
25 //  Module : SALOME
26 //  $Header$
27 //
28 #ifndef _BASICGENERICDESTRUCTOR_HXX_
29 #define _BASICGENERICDESTRUCTOR_HXX_
30
31 #include "SALOME_Basics.hxx"
32
33 #include <list>
34 #include <algorithm>
35 #include <cassert>
36 #include <typeinfo>
37 #include <iostream>
38 #include <cstdlib>
39 #include <pthread.h>
40
41 //#define _DEVDEBUG_
42
43 #ifdef _DEVDEBUG_
44 #define MYDEVTRACE {std::cerr << __FILE__ << " [" << __LINE__ << "] : ";}
45 #define DEVTRACE(msg) {MYDEVTRACE; std::cerr<<msg<<std::endl<<std::flush;}
46 #else
47 #define MYDEVTRACE
48 #define DEVTRACE(msg)
49 #endif
50
51 // ============================================================================
52 /*!
53  * The PROTECTED_DELETE base class provides a protected destructor. 
54  * The only way to use PROTECTED_DELETE is inheritance:
55  *   example: class LocalTraceBufferPool : public PROTECTED_DELETE
56  * Herited class destructor must stay protected.
57  * Normal use is:
58  * - create an instance of herited class on the heap (new),
59  * - use addObj(instance) to store the instance on the static list _objList,
60  * - delete instance with deleteInstance(instance)
61  *
62  * This class is utilised with GENERIC_DESTRUCTOR and DESTRUCTOR_OF, 
63  * to program automatic deletion of objects at the end of the process, while
64  * keeping the possibility of an early destruction, if required. This is used
65  * for unit testing and trace mecanism.
66  */ 
67 // ============================================================================
68
69 class BASICS_EXPORT PROTECTED_DELETE
70 {
71 public:
72   static void deleteInstance(PROTECTED_DELETE *anObject);
73   static void addObj(PROTECTED_DELETE *anObject);
74
75 protected:
76   virtual ~PROTECTED_DELETE();
77   static std::list<PROTECTED_DELETE*> _objList;
78
79 private:
80   static pthread_mutex_t _listMutex;
81 };
82
83 // ============================================================================
84 /*!
85  * The GENERIC_DESTRUCTOR abstract class describes the comportement of any
86  * destruction object. This type is used to create a list of miscellaneous
87  * destruction objects.
88  *
89  * The only way to use the GENERIC_DESTRUCTOR class is inheritance:
90  *   class SPECIFIC_DESTRUCTOR : public GENERIC_DESTRUCTOR
91  * 
92  * A generic destructor provides two methods:
93  * -# a static method to add a destruction (object) to be performed:
94  *    GENERIC_DESTRUCTOR::Add(GENERIC_DESTRUCTOR &anObject);
95  *    The Destruction object is stored in a list of pointer to
96  *    GENERIC_DESTRUCTOR objects.
97  * -# an object method to execute the destruction : operator()().
98  */ 
99 // ============================================================================
100
101 class BASICS_EXPORT GENERIC_DESTRUCTOR
102 {
103 public :
104   static std::list<GENERIC_DESTRUCTOR*> *Destructors;
105
106   virtual ~GENERIC_DESTRUCTOR() {};
107   static const int Add(GENERIC_DESTRUCTOR &anObject);
108   virtual void operator()(void) = 0;
109 };
110
111 // ============================================================================
112 /*! 
113  * The DESTRUCTOR_OF class allows the user to program - at any moment - the
114  * destruction of an object at the end of the process.
115  *
116  * Example: the POINT ptrPoint will be destroyed at the end of the process
117  * (atexit).
118  *
119  * POINT *ptrPoint = new POINT ;
120  *
121  * DESTRUCTOR_OF<POINT> *ptrDestruct = new DESTRUCTOR_OF<POINT>(*ptrPoint);
122  * 
123  * Note that neither ptrPoint, nor ptrDestruct should be destroyed by the user.
124  * 
125  * The destruction object must be created dynamically because it suscribes
126  * itself in the list of destruction to be performed at the end of the process.
127  */ 
128 // ============================================================================
129
130 template <class TYPE> class DESTRUCTOR_OF : public GENERIC_DESTRUCTOR
131 {
132 public:
133   /*!
134     Programs the destruction at the end of the process, of the object anObject.
135     This method records in _objectPtr the address of an object to be destroyed 
136     at the end of the process
137   */
138   DESTRUCTOR_OF(TYPE &anObject):
139     _objectPtr(&anObject)
140   {
141     DEVTRACE(" DESTRUCTOR_OF " << typeid(anObject).name() 
142              << " " << _objectPtr << " " << this );
143     PROTECTED_DELETE::addObj(_objectPtr);
144     assert(GENERIC_DESTRUCTOR::Add(*this) >= 0);
145   }
146
147   /*!
148     Performs the destruction of the object.
149     This method really destroys the object pointed by _objectPtr. 
150     It should be called at the end of the process (i.e. at exit).
151   */
152   virtual void operator()(void)
153   {
154     if (_objectPtr)
155       {
156         DEVTRACE("DESTRUCTOR_OF<>::operator() " << _objectPtr);
157         if (_objectPtr) PROTECTED_DELETE::deleteInstance(_objectPtr);
158         _objectPtr = NULL;
159       }
160   }
161
162   virtual ~DESTRUCTOR_OF()
163   {
164     DEVTRACE("~DESTRUCTOR_OF() " << this);
165     assert(!_objectPtr);
166   }
167
168 private:
169   TYPE *_objectPtr;
170 };
171
172 # endif