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