]> SALOME platform Git repositories - modules/kernel.git/commitdiff
Salome HOME
PR: A pure C++ generic destructor with protected delete
authorprascle <prascle>
Mon, 3 Oct 2005 09:45:48 +0000 (09:45 +0000)
committerprascle <prascle>
Mon, 3 Oct 2005 09:45:48 +0000 (09:45 +0000)
src/Basics/BasicsGenericDestructor.cxx [new file with mode: 0644]
src/Basics/BasicsGenericDestructor.hxx [new file with mode: 0644]
src/Basics/Makefile.in [new file with mode: 0644]

diff --git a/src/Basics/BasicsGenericDestructor.cxx b/src/Basics/BasicsGenericDestructor.cxx
new file mode 100644 (file)
index 0000000..f770790
--- /dev/null
@@ -0,0 +1,177 @@
+//  SALOME Basics : general SALOME definitions and tools (C++ part - no CORBA)
+//
+//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
+// 
+//  This library is free software; you can redistribute it and/or 
+//  modify it under the terms of the GNU Lesser General Public 
+//  License as published by the Free Software Foundation; either 
+//  version 2.1 of the License. 
+// 
+//  This library is distributed in the hope that it will be useful, 
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+//  Lesser General Public License for more details. 
+// 
+//  You should have received a copy of the GNU Lesser General Public 
+//  License along with this library; if not, write to the Free Software 
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
+// 
+//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
+//
+//
+//
+//  File   : BasicGenericDestructor.cxx
+//  Author : Antoine YESSAYAN, Paul RASCLE, EDF
+//  Module : SALOME
+//  $Header$
+
+#include <iostream>
+#include <list>
+#include <cstdlib>
+
+#include "BasicsGenericDestructor.hxx"
+
+using namespace std;
+
+void HouseKeeping();
+
+std::list<PROTECTED_DELETE*> PROTECTED_DELETE::_objList;
+pthread_mutex_t PROTECTED_DELETE::_listMutex;
+
+std::list<GENERIC_DESTRUCTOR*> *GENERIC_DESTRUCTOR::Destructors = 0;
+static bool atExitSingletonDone = false ;
+
+void PROTECTED_DELETE::deleteInstance(PROTECTED_DELETE *anObject)
+  {
+    if (std::find(_objList.begin(), _objList.end(),anObject) == _objList.end())
+      return;
+    else
+      {
+       int ret;
+       ret = pthread_mutex_lock(&_listMutex); // acquire lock, an check again
+       if (std::find(_objList.begin(), _objList.end(), anObject)
+           != _objList.end())
+         {
+           cerr << "PROTECTED_DELETE::deleteInstance1 " << anObject << endl;
+           delete anObject;
+           cerr << "PROTECTED_DELETE::deleteInstance2 " << &_objList << endl;
+           _objList.remove(anObject);
+           cerr << "PROTECTED_DELETE::deleteInstance3" << endl;
+         }
+       ret = pthread_mutex_unlock(&_listMutex); // release lock
+      }
+  }
+
+void PROTECTED_DELETE::addObj(PROTECTED_DELETE *anObject)
+{
+  cerr << "PROTECTED_DELETE::addObj " << anObject << endl;
+  _objList.push_back(anObject);
+}
+
+PROTECTED_DELETE::~PROTECTED_DELETE()
+{
+  cerr << "PROTECTED_DELETE::~PROTECTED_DELETE()" << endl;
+}
+
+// ============================================================================
+/*! 
+ * To execute only once GENERIC_DESTRUCTOR::HouseKeeping et the end of process,
+ * a dedicated object is created, as a singleton: atExitSingleton.
+ * When the singleton is created, the HouseKeeping() function is registered in
+ * atExit().
+ * Destructors is a list created on heap, and deleted by HouseKeeping(), with
+ * the list content.
+ */
+// ============================================================================
+
+class atExitSingleton
+{
+public:
+  atExitSingleton(bool Make_ATEXIT)
+  {
+    if (Make_ATEXIT && !atExitSingletonDone)
+      {
+       cerr << "atExitSingleton(" << Make_ATEXIT << ")" << endl;
+       assert(GENERIC_DESTRUCTOR::Destructors == 0);
+       GENERIC_DESTRUCTOR::Destructors = new std::list<GENERIC_DESTRUCTOR*>;
+       int cr = atexit(HouseKeeping);
+       assert(cr == 0);
+       atExitSingletonDone = true;
+      }
+  }
+
+  ~atExitSingleton()
+  {
+    cerr << "atExitSingleton::~atExitSingleton()" << endl << flush;
+  }
+};
+
+//! static singleton for atExitSingleton class
+
+static atExitSingleton HouseKeeper = atExitSingleton(false);
+
+// ============================================================================
+/*! 
+ *  Executes all objects of type DESTRUCTOR_OF in the Destructors list. 
+ *  Deletes  all objects of type DESTRUCTOR_OF in the Destructors list.
+ *  Deletes the list.
+ */
+// ============================================================================
+
+void HouseKeeping( void )
+{
+  cerr << "HouseKeeping()" << endl;
+  assert(GENERIC_DESTRUCTOR::Destructors);
+  if(GENERIC_DESTRUCTOR::Destructors->size())
+    {
+      std::list<GENERIC_DESTRUCTOR*>::iterator it =
+       GENERIC_DESTRUCTOR::Destructors->end();
+
+      do
+       {
+         it-- ;
+         GENERIC_DESTRUCTOR* ptr = *it ;
+         cerr << "HouseKeeping() " << typeid(ptr).name() << endl;
+         (*ptr)();
+         delete ptr ;
+       }
+      while (it !=  GENERIC_DESTRUCTOR::Destructors->begin()) ;
+
+      cerr << "HouseKeeping() end list "<< endl;
+      GENERIC_DESTRUCTOR::Destructors->clear() ;
+      assert(GENERIC_DESTRUCTOR::Destructors->size() == 0);
+      assert(GENERIC_DESTRUCTOR::Destructors->empty());
+      cerr << "HouseKeeping()after clear "<< endl;
+    }
+
+  delete GENERIC_DESTRUCTOR::Destructors;
+  GENERIC_DESTRUCTOR::Destructors = 0;
+  cerr << "HouseKeeping() very end "<< endl;
+  return ;
+}
+
+// ============================================================================
+/*!
+ * Adds a destruction object to the list of actions to be performed at the end
+ * of the process
+ */
+// ============================================================================
+
+const int GENERIC_DESTRUCTOR::Add(GENERIC_DESTRUCTOR &anObject)
+{
+  cerr << "GENERIC_DESTRUCTOR::Add("<<typeid(anObject).name()<<") "
+       << &anObject << endl;
+  if (!atExitSingletonDone)
+    {
+      HouseKeeper = atExitSingleton(true);
+    }
+  assert(Destructors);
+//   if (std::find(Destructors->begin(), Destructors->end(), &anObject)
+//       == Destructors->end())
+//     {
+//       Destructors->push_back(&anObject);
+//     }
+  Destructors->push_back(&anObject);
+  return Destructors->size();
+}
diff --git a/src/Basics/BasicsGenericDestructor.hxx b/src/Basics/BasicsGenericDestructor.hxx
new file mode 100644 (file)
index 0000000..607d849
--- /dev/null
@@ -0,0 +1,160 @@
+//  SALOME Basics : general SALOME definitions and tools (C++ part - no CORBA)
+//
+//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
+// 
+//  This library is free software; you can redistribute it and/or 
+//  modify it under the terms of the GNU Lesser General Public 
+//  License as published by the Free Software Foundation; either 
+//  version 2.1 of the License. 
+// 
+//  This library is distributed in the hope that it will be useful, 
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+//  Lesser General Public License for more details. 
+// 
+//  You should have received a copy of the GNU Lesser General Public 
+//  License along with this library; if not, write to the Free Software 
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
+// 
+//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
+//
+//
+//
+//  File   : BasicGenericDestructor.hxx
+//  Author : Antoine YESSAYAN, Paul RASCLE, EDF
+//  Module : SALOME
+//  $Header$
+
+#ifndef _BASICGENERICDESTRUCTOR_HXX_
+#define _BASICGENERICDESTRUCTOR_HXX_
+
+#include <list>
+#include <algorithm>
+#include <cassert>
+#include <typeinfo>
+#include <pthread.h>
+
+#if defined BASICS_EXPORTS
+#if defined WIN32
+#define BASICS_EXPORT __declspec( dllexport )
+#else
+#define BASICS_EXPORT
+#endif
+#else
+#if defined WNT
+#define BASICS_EXPORT __declspec( dllimport )
+#else
+#define BASICS_EXPORT
+#endif
+#endif
+
+class PROTECTED_DELETE
+{
+public:
+  static void deleteInstance(PROTECTED_DELETE *anObject);
+  static void addObj(PROTECTED_DELETE *anObject);
+
+protected:
+  virtual ~PROTECTED_DELETE();
+  static std::list<PROTECTED_DELETE*> _objList;
+
+private:
+  static pthread_mutex_t _listMutex;
+};
+
+// ============================================================================
+/*!
+ * The GENERIC_DESTRUCTOR abstract class describes the comportement of any
+ * destruction object. This type is used to create a list of miscellaneous
+ * destruction objects.
+ *
+ * The only way to use the GENERIC_DESTRUCTOR class is inheritance:
+ *   class SPECIFIC_DESTRUCTOR : public GENERIC_DESTRUCTOR
+ * 
+ * A generic destructor provides two methods:
+ * -# a static method to add a destruction (object) to be performed:
+ *    GENERIC_DESTRUCTOR::Add(GENERIC_DESTRUCTOR &anObject);
+ *    The Destruction object is stored in a list of pointer to
+ *    GENERIC_DESTRUCTOR objects.
+ * -# an object method to execute the destruction : operator()().
+ */ 
+// ============================================================================
+
+class GENERIC_DESTRUCTOR
+{
+public :
+  BASICS_EXPORT static std::list<GENERIC_DESTRUCTOR*> *Destructors;
+
+  virtual ~GENERIC_DESTRUCTOR() {};
+  BASICS_EXPORT static const int Add(GENERIC_DESTRUCTOR &anObject);
+  BASICS_EXPORT virtual void operator()(void) = 0;
+};
+
+// ============================================================================
+/*! 
+ * The DESTRUCTOR_OF class allows the user to program - at any moment - the
+ * destruction of an object at the end of the process.
+ *
+ * Example: the POINT ptrPoint will be destroyed at the end of the process
+ * (atexit).
+ *
+ * POINT *ptrPoint = new POINT ;
+ *
+ * DESTRUCTOR_OF<POINT> *ptrDestruct = new DESTRUCTOR_OF<POINT>(*ptrPoint);
+ * 
+ * Note that neither ptrPoint, nor ptrDestruct should be destroyed by the user.
+ * 
+ * The destruction object must be created dynamically because it suscribes
+ * itself in the list of destruction to be performed at the end of the process.
+ */ 
+// ============================================================================
+
+template <class TYPE> class DESTRUCTOR_OF : public GENERIC_DESTRUCTOR
+{
+
+public:
+  /*!
+    Programs the destruction at the end of the process, of the object anObject.
+    This method records in _objectPtr the address of an object to be destroyed 
+    at the end of the process
+  */
+  DESTRUCTOR_OF(TYPE &anObject):
+    _objectPtr(&anObject)
+  {
+    std::cerr << " DESTRUCTOR_OF " << typeid(anObject).name() 
+             << " " << _objectPtr << " " << this << endl;
+    PROTECTED_DELETE::addObj(_objectPtr);
+    assert(GENERIC_DESTRUCTOR::Add(*this) >= 0);
+  }
+
+  /*!
+    Performs the destruction of the object.
+    This method really destroys the object pointed by _objectPtr. 
+    It should be called at the end of the process (i.e. at exit).
+  */
+  virtual void operator()(void)
+  {
+    if (_objectPtr)
+      {
+       //TYPE* aPtr = static_cast<TYPE*>(_objectPtr);
+       //std::cerr << "DESTRUCTOR_OF<" << typeid(*aPtr).name() 
+        //          << ">::operator() " << _objectPtr << " " << aPtr << endl;
+       //if (aPtr) PROTECTED_DELETE::deleteInstance(_objectPtr);
+       std::cerr << "DESTRUCTOR_OF<>::operator() " << _objectPtr << endl;
+       if (_objectPtr) PROTECTED_DELETE::deleteInstance(_objectPtr);
+       _objectPtr = NULL;
+      }
+  }
+
+  virtual ~DESTRUCTOR_OF()
+  {
+    cerr << "~DESTRUCTOR_OF() " << this << endl;
+    assert(!_objectPtr);
+  }
+
+private:
+  TYPE *_objectPtr;
+};
+
+# endif
diff --git a/src/Basics/Makefile.in b/src/Basics/Makefile.in
new file mode 100644 (file)
index 0000000..2abc138
--- /dev/null
@@ -0,0 +1,52 @@
+#  SALOMELocalTrace : log on local machine
+#
+#  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+#  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
+# 
+#  This library is free software; you can redistribute it and/or 
+#  modify it under the terms of the GNU Lesser General Public 
+#  License as published by the Free Software Foundation; either 
+#  version 2.1 of the License. 
+# 
+#  This library is distributed in the hope that it will be useful, 
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of 
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#  Lesser General Public License for more details. 
+# 
+#  You should have received a copy of the GNU Lesser General Public 
+#  License along with this library; if not, write to the Free Software 
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
+# 
+#  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
+#
+#
+#
+#  File   : Makefile.in
+#  Author : Paul RASCLE (EDF)
+#  Module : SALOME
+#  $Header$
+
+top_srcdir=@top_srcdir@
+top_builddir=../..
+srcdir=@srcdir@
+VPATH=.:@srcdir@:@top_srcdir@/idl
+
+
+@COMMENCE@
+
+# header files  
+EXPORT_HEADERS= \
+ BasicsGenericDestructor.hxx 
+
+EXPORT_PYSCRIPTS = 
+
+# Libraries targets
+
+LIB = libSALOMEBasics.la 
+LIB_SRC = BasicsGenericDestructor.cxx
+
+LIBS= @LIBS@ 
+#LDFLAGS+= 
+
+
+@CONCLUDE@