From 8feb0b26c5a20b141fa33c17329d28fdd4a85519 Mon Sep 17 00:00:00 2001 From: prascle Date: Mon, 3 Oct 2005 09:45:48 +0000 Subject: [PATCH] PR: A pure C++ generic destructor with protected delete --- src/Basics/BasicsGenericDestructor.cxx | 177 +++++++++++++++++++++++++ src/Basics/BasicsGenericDestructor.hxx | 160 ++++++++++++++++++++++ src/Basics/Makefile.in | 52 ++++++++ 3 files changed, 389 insertions(+) create mode 100644 src/Basics/BasicsGenericDestructor.cxx create mode 100644 src/Basics/BasicsGenericDestructor.hxx create mode 100644 src/Basics/Makefile.in diff --git a/src/Basics/BasicsGenericDestructor.cxx b/src/Basics/BasicsGenericDestructor.cxx new file mode 100644 index 000000000..f7707902f --- /dev/null +++ b/src/Basics/BasicsGenericDestructor.cxx @@ -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 +#include +#include + +#include "BasicsGenericDestructor.hxx" + +using namespace std; + +void HouseKeeping(); + +std::list PROTECTED_DELETE::_objList; +pthread_mutex_t PROTECTED_DELETE::_listMutex; + +std::list *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; + 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::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("<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 index 000000000..607d849d4 --- /dev/null +++ b/src/Basics/BasicsGenericDestructor.hxx @@ -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 +#include +#include +#include +#include + +#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 _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 *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 *ptrDestruct = new DESTRUCTOR_OF(*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 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(_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 index 000000000..2abc13887 --- /dev/null +++ b/src/Basics/Makefile.in @@ -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@ -- 2.39.2