Salome HOME
updated copyright message
[modules/kernel.git] / src / Basics / BasicsGenericDestructor.cxx
1 // Copyright (C) 2007-2023  CEA, EDF, 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, or (at your option) any later version.
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         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         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 #ifndef _DEBUG_
121         atexit(HouseKeeping);
122 #else
123         int cr = atexit(HouseKeeping);
124         assert(cr == 0);
125 #endif
126         atExitSingletonDone = true;
127       }
128   }
129
130   ~atExitSingleton()
131   {
132     DEVTRACE("atExitSingleton::~atExitSingleton()");
133   }
134 };
135
136 //! static singleton for atExitSingleton class
137
138 static atExitSingleton HouseKeeper = atExitSingleton(false);
139
140 // ============================================================================
141 /*! 
142  *  Executes all objects of type DESTRUCTOR_OF in the Destructors list. 
143  *  Deletes  all objects of type DESTRUCTOR_OF in the Destructors list.
144  *  Deletes the list.
145  */
146 // ============================================================================
147
148 void HouseKeeping( void )
149 {
150   DEVTRACE("HouseKeeping()");
151   assert(GENERIC_DESTRUCTOR::Destructors);
152   if(GENERIC_DESTRUCTOR::Destructors->size())
153     {
154       std::list<GENERIC_DESTRUCTOR*>::iterator it =
155         GENERIC_DESTRUCTOR::Destructors->end();
156
157       do
158         {
159           it-- ;
160           GENERIC_DESTRUCTOR* ptr = *it ;
161           DEVTRACE("HouseKeeping() " << typeid(ptr).name());
162           (*ptr)();
163           delete ptr ;
164         }
165       while (it !=  GENERIC_DESTRUCTOR::Destructors->begin()) ;
166
167       DEVTRACE("HouseKeeping() end list ");
168       GENERIC_DESTRUCTOR::Destructors->clear() ;
169       assert(GENERIC_DESTRUCTOR::Destructors->size() == 0);
170       assert(GENERIC_DESTRUCTOR::Destructors->empty());
171       DEVTRACE("HouseKeeping()after clear ");
172     }
173
174   delete GENERIC_DESTRUCTOR::Destructors;
175   GENERIC_DESTRUCTOR::Destructors = 0;
176   atExitSingletonDone = false ;
177   DEVTRACE("HouseKeeping() very end ");
178   return ;
179 }
180
181 // ============================================================================
182 /*!
183  * Adds a destruction object to the list of actions to be performed at the end
184  * of the process
185  */
186 // ============================================================================
187
188 int GENERIC_DESTRUCTOR::Add(GENERIC_DESTRUCTOR &anObject)
189 {
190   DEVTRACE("GENERIC_DESTRUCTOR::Add("<<typeid(anObject).name()<<") "
191            << &anObject);
192   if (!atExitSingletonDone)
193     {
194       HouseKeeper = atExitSingleton(true);
195     }
196   assert(Destructors);
197   Destructors->push_back(&anObject);
198   return (int)Destructors->size();
199 }