Salome HOME
Merge from V5_1_3_BR 07/12/2009
[modules/kernel.git] / src / Basics / BasicsGenericDestructor.cxx
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.cxx
24 //  Author : Antoine YESSAYAN, Paul RASCLE, EDF
25 //  Module : SALOME
26 //  $Header$
27 //
28 #include <iostream>
29 #include <list>
30 #include <cstdlib>
31
32 #include "BasicsGenericDestructor.hxx"
33
34 using namespace std;
35
36 void HouseKeeping();
37
38 std::list<PROTECTED_DELETE*> PROTECTED_DELETE::_objList;
39 #ifndef WIN32
40 pthread_mutex_t PROTECTED_DELETE::_listMutex;
41 #else
42 pthread_mutex_t PROTECTED_DELETE::_listMutex =
43   PTHREAD_MUTEX_INITIALIZER;
44 #endif
45
46 std::list<GENERIC_DESTRUCTOR*> *GENERIC_DESTRUCTOR::Destructors = 0;
47 static bool atExitSingletonDone = false ;
48
49 // ============================================================================
50 /*! 
51  *  deleteInstance deletes only once the object. Only object present on the
52  *  static list of PROTECTED_DELETE* are deleted, then removed of the list.
53  *  The operation is protected by a mutex.
54  */
55 // ============================================================================
56
57 void PROTECTED_DELETE::deleteInstance(PROTECTED_DELETE *anObject)
58   {
59     if (std::find(_objList.begin(), _objList.end(),anObject) == _objList.end())
60       return;
61     else
62       {
63         int ret;
64         ret = pthread_mutex_lock(&_listMutex); // acquire lock, an check again
65         if (std::find(_objList.begin(), _objList.end(), anObject)
66             != _objList.end())
67           {
68             DEVTRACE("PROTECTED_DELETE::deleteInstance1 " << anObject);
69             delete anObject;
70             DEVTRACE("PROTECTED_DELETE::deleteInstance2 " << &_objList);
71             _objList.remove(anObject);
72           }
73         ret = pthread_mutex_unlock(&_listMutex); // release lock
74       }
75   }
76
77 // ============================================================================
78 /*! 
79  * To allow a further destruction of a PRTECTED_DELETE object, it must be added
80  * to the static list of PROTECTED_DELETE*
81  */
82 // ============================================================================
83
84 void PROTECTED_DELETE::addObj(PROTECTED_DELETE *anObject)
85 {
86   DEVTRACE("PROTECTED_DELETE::addObj " << anObject);
87   _objList.push_back(anObject);
88 }
89
90 // ============================================================================
91 /*! 
92  *  Herited classes have there own destructors
93  */
94 // ============================================================================
95
96 PROTECTED_DELETE::~PROTECTED_DELETE()
97 {
98   DEVTRACE("PROTECTED_DELETE::~PROTECTED_DELETE()");
99 }
100
101 // ============================================================================
102 /*! 
103  * To execute only once GENERIC_DESTRUCTOR::HouseKeeping et the end of process,
104  * a dedicated object is created, as a singleton: atExitSingleton.
105  * When the singleton is created, the HouseKeeping() function is registered in
106  * atExit().
107  * Destructors is a list created on heap, and deleted by HouseKeeping(), with
108  * the list content.
109  */
110 // ============================================================================
111
112 class atExitSingleton
113 {
114 public:
115   atExitSingleton(bool Make_ATEXIT)
116   {
117     if (Make_ATEXIT && !atExitSingletonDone)
118       {
119         DEVTRACE("atExitSingleton(" << Make_ATEXIT << ")");
120         assert(GENERIC_DESTRUCTOR::Destructors == 0);
121         GENERIC_DESTRUCTOR::Destructors = new std::list<GENERIC_DESTRUCTOR*>;
122         int cr = atexit(HouseKeeping);
123         assert(cr == 0);
124         atExitSingletonDone = true;
125       }
126   }
127
128   ~atExitSingleton()
129   {
130     DEVTRACE("atExitSingleton::~atExitSingleton()");
131   }
132 };
133
134 //! static singleton for atExitSingleton class
135
136 static atExitSingleton HouseKeeper = atExitSingleton(false);
137
138 // ============================================================================
139 /*! 
140  *  Executes all objects of type DESTRUCTOR_OF in the Destructors list. 
141  *  Deletes  all objects of type DESTRUCTOR_OF in the Destructors list.
142  *  Deletes the list.
143  */
144 // ============================================================================
145
146 void HouseKeeping( void )
147 {
148   DEVTRACE("HouseKeeping()");
149   assert(GENERIC_DESTRUCTOR::Destructors);
150   if(GENERIC_DESTRUCTOR::Destructors->size())
151     {
152       std::list<GENERIC_DESTRUCTOR*>::iterator it =
153         GENERIC_DESTRUCTOR::Destructors->end();
154
155       do
156         {
157           it-- ;
158           GENERIC_DESTRUCTOR* ptr = *it ;
159           DEVTRACE("HouseKeeping() " << typeid(ptr).name());
160           (*ptr)();
161           delete ptr ;
162         }
163       while (it !=  GENERIC_DESTRUCTOR::Destructors->begin()) ;
164
165       DEVTRACE("HouseKeeping() end list ");
166       GENERIC_DESTRUCTOR::Destructors->clear() ;
167       assert(GENERIC_DESTRUCTOR::Destructors->size() == 0);
168       assert(GENERIC_DESTRUCTOR::Destructors->empty());
169       DEVTRACE("HouseKeeping()after clear ");
170     }
171
172   delete GENERIC_DESTRUCTOR::Destructors;
173   GENERIC_DESTRUCTOR::Destructors = 0;
174   atExitSingletonDone = false ;
175   DEVTRACE("HouseKeeping() very end ");
176   return ;
177 }
178
179 // ============================================================================
180 /*!
181  * Adds a destruction object to the list of actions to be performed at the end
182  * of the process
183  */
184 // ============================================================================
185
186 const int GENERIC_DESTRUCTOR::Add(GENERIC_DESTRUCTOR &anObject)
187 {
188   DEVTRACE("GENERIC_DESTRUCTOR::Add("<<typeid(anObject).name()<<") "
189            << &anObject);
190   if (!atExitSingletonDone)
191     {
192       HouseKeeper = atExitSingleton(true);
193     }
194   assert(Destructors);
195   Destructors->push_back(&anObject);
196   return Destructors->size();
197 }