00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
00044
00045 struct BasicCleanupFunctorBase {
00046 virtual void operator()()=0;
00047 };
00048
00049 template <class T>
00050 struct BasicCleanupFunctor : public BasicCleanupFunctorBase {
00051 void (T::*fpt)();
00052 T* pt2Object;
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
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