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