00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef _SCAVENGER_H_
00023 #define _SCAVENGER_H_
00024
00025 #include "system/System.h"
00026
00027 #include <vector>
00028 #include <list>
00029 #include <sys/time.h>
00030 #include <QMutex>
00031 #include <iostream>
00032
00044 template <typename T>
00045 class Scavenger
00046 {
00047 public:
00048 Scavenger(int sec = 2, int defaultObjectListSize = 200);
00049 ~Scavenger();
00050
00055 void claim(T *t);
00056
00061 void scavenge(bool clearNow = false);
00062
00063 protected:
00064 typedef std::pair<T *, int> ObjectTimePair;
00065 typedef std::vector<ObjectTimePair> ObjectTimeList;
00066 ObjectTimeList m_objects;
00067 int m_sec;
00068
00069 typedef std::list<T *> ObjectList;
00070 ObjectList m_excess;
00071 int m_lastExcess;
00072 QMutex m_excessMutex;
00073 void pushExcess(T *);
00074 void clearExcess(int);
00075
00076 unsigned int m_claimed;
00077 unsigned int m_scavenged;
00078 };
00079
00084 template <typename T>
00085 class ScavengerArrayWrapper
00086 {
00087 public:
00088 ScavengerArrayWrapper(T *array) : m_array(array) { }
00089 ~ScavengerArrayWrapper() { delete[] m_array; }
00090
00091 private:
00092 T *m_array;
00093 };
00094
00095
00096 template <typename T>
00097 Scavenger<T>::Scavenger(int sec, int defaultObjectListSize) :
00098 m_objects(ObjectTimeList(defaultObjectListSize)),
00099 m_sec(sec),
00100 m_lastExcess(0),
00101 m_claimed(0),
00102 m_scavenged(0)
00103 {
00104 }
00105
00106 template <typename T>
00107 Scavenger<T>::~Scavenger()
00108 {
00109 if (m_scavenged < m_claimed) {
00110 for (size_t i = 0; i < m_objects.size(); ++i) {
00111 ObjectTimePair &pair = m_objects[i];
00112 if (pair.first != 0) {
00113 T *ot = pair.first;
00114 pair.first = 0;
00115 delete ot;
00116 ++m_scavenged;
00117 }
00118 }
00119 }
00120
00121 clearExcess(0);
00122 }
00123
00124 template <typename T>
00125 void
00126 Scavenger<T>::claim(T *t)
00127 {
00128
00129
00130 struct timeval tv;
00131 (void)gettimeofday(&tv, 0);
00132 int sec = tv.tv_sec;
00133
00134 for (size_t i = 0; i < m_objects.size(); ++i) {
00135 ObjectTimePair &pair = m_objects[i];
00136 if (pair.first == 0) {
00137 pair.second = sec;
00138 pair.first = t;
00139 ++m_claimed;
00140 return;
00141 }
00142 }
00143
00144 std::cerr << "WARNING: Scavenger::claim(" << t << "): run out of slots, "
00145 << "using non-RT-safe method" << std::endl;
00146 pushExcess(t);
00147 }
00148
00149 template <typename T>
00150 void
00151 Scavenger<T>::scavenge(bool clearNow)
00152 {
00153
00154
00155 if (m_scavenged >= m_claimed) return;
00156
00157 struct timeval tv;
00158 (void)gettimeofday(&tv, 0);
00159 int sec = tv.tv_sec;
00160
00161 for (size_t i = 0; i < m_objects.size(); ++i) {
00162 ObjectTimePair &pair = m_objects[i];
00163 if (clearNow ||
00164 (pair.first != 0 && pair.second + m_sec < sec)) {
00165 T *ot = pair.first;
00166 pair.first = 0;
00167 delete ot;
00168 ++m_scavenged;
00169 }
00170 }
00171
00172 if (sec > m_lastExcess + m_sec) {
00173 clearExcess(sec);
00174 }
00175 }
00176
00177 template <typename T>
00178 void
00179 Scavenger<T>::pushExcess(T *t)
00180 {
00181 m_excessMutex.lock();
00182 m_excess.push_back(t);
00183 struct timeval tv;
00184 (void)gettimeofday(&tv, 0);
00185 m_lastExcess = tv.tv_sec;
00186 m_excessMutex.unlock();
00187 }
00188
00189 template <typename T>
00190 void
00191 Scavenger<T>::clearExcess(int sec)
00192 {
00193 m_excessMutex.lock();
00194 for (typename ObjectList::iterator i = m_excess.begin();
00195 i != m_excess.end(); ++i) {
00196 delete *i;
00197 }
00198 m_excess.clear();
00199 m_lastExcess = sec;
00200 m_excessMutex.unlock();
00201 }
00202
00203 #endif