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