basiccleanuphandler.h

Go to the documentation of this file.
00001 /*******************************************************************\
00002 
00003                    SESAME project software license
00004 
00005           Copyright (C) 2002, 2003 University of Amsterdam
00006 
00007     This program is free software; you can redistribute it and/or
00008      modify it under the terms of the GNU General Public License
00009     as published by the Free Software Foundation; either version 2
00010         of the License, or (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015              GNU General Public License for more details.
00016 
00017   You should have received a copy of the GNU General Public License
00018      along with this program; if not, write to the Free Software
00019       Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00020                            02111-1307, USA.
00021 
00022       For information regarding the SESAME software project see
00023               http://sesamesim.sourceforge.net or email
00024                     jcofflan@users.sourceforge.net
00025 
00026 \*******************************************************************/
00027 
00028 #ifndef BASICCLEANUPHANDLER_H
00029 #define BASICCLEANUPHANDLER_H
00030 
00031 #include <iostream>
00032 #include <map>
00033 #include <list>
00034 #include <typeinfo>
00035 #include <signal.h>
00036 #include <unistd.h>
00037 #include <stdlib.h>
00038 
00039 #include <BasicUtils/BasicThread.h>
00040 #include <BasicUtils/BasicLockable.h>
00041 #include <BasicUtils/BasicException.h>
00042 
00043 //#define BASICCLEANUPHANDLER_DEBUG
00044 
00045 struct BasicCleanupFunctorBase {
00046   virtual void operator()()=0;
00047 };
00048 
00049 template <class T>
00050 struct BasicCleanupFunctor : public BasicCleanupFunctorBase {
00051   void (T::*fpt)();   // pointer to member function
00052   T* pt2Object;  // pointer to object
00053 
00054   public:
00055   BasicCleanupFunctor(T* _pt2Object, void(T::*_fpt)())
00056   {pt2Object = _pt2Object;  fpt = _fpt;};
00057 
00058   virtual void operator()() {(*pt2Object.*fpt)();}
00059 };
00060 
00061 
00062 class BasicCleanupHandler {
00063   static bool initialized;
00064 
00065   typedef std::list<BasicCleanupFunctorBase *> object_list_t;
00066   typedef std::map<BasicCleanupFunctorBase *, object_list_t::iterator>
00067   object_map_t;
00068 
00069   static object_list_t *object_list;
00070   static object_map_t *object_map;
00071 
00072   static const int numSignals;
00073   static int signals[];
00074 
00075   typedef void (*sighandler_t)(int);
00076   static sighandler_t oldHandlers[6];
00077 
00078   static int cleanupSig;
00079   static BasicThread *cleaner;
00080 
00081  public:
00082 
00083   static void signalHandler(int sig) {
00084 #ifdef BASICCLEANUPHANDLER_DEBUG
00085     std::cerr << "Entering signal handler" << std::endl;
00086 #endif
00087 
00088     // Restore old handlers
00089     for (int i = 0; i < numSignals; i++) {
00090       signal(signals[i], SIG_IGN);
00091     }
00092 
00093     cleanupSig = sig;
00094   }
00095 
00096   static void doCleanup() {
00097     int cleanCnt = 0;
00098 
00099     object_map->clear();
00100     while (!object_list->empty()) {
00101       BasicCleanupFunctorBase *obj;
00102       obj = object_list->front();
00103       object_list->pop_front();
00104 
00105 #ifdef BASICCLEANUPHANDLER_DEBUG
00106       cout << "Cleaning up  at " << obj << endl;
00107 #endif
00108 
00109       (*obj)();
00110       cleanCnt++;
00111     }
00112 
00113     if (cleanCnt)
00114       std::cerr << "BasicCleanupHandler cleaned up " << cleanCnt
00115                 << " orphaned resource(s)!" << std::endl;
00116   }
00117 
00118   static void *cleanup(void *p) {
00119 #ifdef BASICCLEANUPHANDLER_DEBUG
00120     cout << "Started cleaner" << endl;
00121 #endif
00122 
00123     while (!cleanupSig) usleep(250);
00124 
00125     doCleanup();
00126 
00127     exit(1);
00128   }
00129 
00130   static void initialize() {
00131     if (initialized) return;
00132 
00133     object_list = new object_list_t;
00134     object_map = new object_map_t;
00135 
00136     int i;
00137     for (i = 0; i < numSignals; i++) {
00138       sighandler_t handler = signal(signals[i], signalHandler);
00139       if (handler == SIG_IGN) signal(signals[i], SIG_IGN);
00140       else if (handler != signalHandler) oldHandlers[i] = handler;
00141     }
00142 
00143     cleaner = new BasicThread(cleanup);
00144     cleaner->start();
00145 
00146     atexit(doCleanup);
00147 
00148     initialized = true;
00149   }
00150 
00151   static void regCleanup(BasicCleanupFunctorBase *obj) {
00152 #ifdef BASICCLEANUPHANDLER_DEBUG
00153     cout << "Registering resource " << obj << endl;
00154 #endif
00155 
00156     ASSERT_OR_THROW("NULL obj!", obj);
00157     object_list->push_front(obj);
00158     (*object_map)[obj] = object_list->begin();
00159   }
00160 
00161   static void unregCleanup(BasicCleanupFunctorBase *obj) {
00162     ASSERT_OR_THROW("NULL obj!", obj);
00163 
00164     object_map_t::iterator it = object_map->find(obj);
00165     if (it == object_map->end()) return;
00166 
00167 #ifdef BASICCLEANUPHANDLER_DEBUG
00168     cout << "Unregistering resource " << obj << endl;
00169 #endif
00170 
00171     object_list_t::iterator pos = (*it).second;
00172     object_list->erase(pos);
00173     object_map->erase(it);
00174   }
00175 };
00176 #endif

Generated on Wed Apr 5 20:57:44 2006 for Sesame by  doxygen 1.4.6