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