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