svcore
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 This file copyright 2006 Chris Cannam. 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License as 00011 published by the Free Software Foundation; either version 2 of the 00012 License, or (at your option) any later version. See the file 00013 COPYING included with this distribution for more information. 00014 */ 00015 00016 /* 00017 This is a modified version of a source file from the 00018 Rosegarden MIDI and audio sequencer and notation editor. 00019 This file copyright 2000-2006 Chris Cannam. 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 // std::cerr << "Scavenger::claim(" << t << ")" << std::endl; 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 // std::cerr << "Scavenger::scavenge: scavenged " << m_scavenged << ", claimed " << m_claimed << std::endl; 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