comparison base/Scavenger.h @ 158:74abef65711b

* Fixes pulled across from Rosegarden
author Chris Cannam
date Wed, 16 Aug 2006 14:57:22 +0000
parents 4b2ea82fd0ed
children 0e266fa2510f
comparison
equal deleted inserted replaced
157:c03ec31005e1 158:74abef65711b
23 #define _SCAVENGER_H_ 23 #define _SCAVENGER_H_
24 24
25 #include "system/System.h" 25 #include "system/System.h"
26 26
27 #include <vector> 27 #include <vector>
28 #include <list>
28 #include <sys/time.h> 29 #include <sys/time.h>
30 #include <pthread.h>
31 #include <iostream>
29 32
30 /** 33 /**
31 * A very simple class that facilitates running things like plugins 34 * A very simple class that facilitates running things like plugins
32 * without locking, by collecting unwanted objects and deleting them 35 * without locking, by collecting unwanted objects and deleting them
33 * after a delay so as to be sure nobody's in the middle of using 36 * after a delay so as to be sure nobody's in the middle of using
41 template <typename T> 44 template <typename T>
42 class Scavenger 45 class Scavenger
43 { 46 {
44 public: 47 public:
45 Scavenger(int sec = 2, int defaultObjectListSize = 200); 48 Scavenger(int sec = 2, int defaultObjectListSize = 200);
49 ~Scavenger();
46 50
47 /** 51 /**
48 * Call from an RT thread etc., to pass ownership of t to us. 52 * Call from an RT thread etc., to pass ownership of t to us.
49 * Only one thread should be calling this on any given scavenger. 53 * Only one thread should be calling this on any given scavenger.
50 */ 54 */
60 typedef std::pair<T *, int> ObjectTimePair; 64 typedef std::pair<T *, int> ObjectTimePair;
61 typedef std::vector<ObjectTimePair> ObjectTimeList; 65 typedef std::vector<ObjectTimePair> ObjectTimeList;
62 ObjectTimeList m_objects; 66 ObjectTimeList m_objects;
63 int m_sec; 67 int m_sec;
64 68
69 typedef std::list<T *> ObjectList;
70 ObjectList m_excess;
71 int m_lastExcess;
72 pthread_mutex_t m_excessMutex;
73 void pushExcess(T *);
74 void clearExcess(int);
75
65 unsigned int m_claimed; 76 unsigned int m_claimed;
66 unsigned int m_scavenged; 77 unsigned int m_scavenged;
67 }; 78 };
68 79
69 /** 80 /**
87 m_objects(ObjectTimeList(defaultObjectListSize)), 98 m_objects(ObjectTimeList(defaultObjectListSize)),
88 m_sec(sec), 99 m_sec(sec),
89 m_claimed(0), 100 m_claimed(0),
90 m_scavenged(0) 101 m_scavenged(0)
91 { 102 {
103 pthread_mutex_init(&m_excessMutex, NULL);
104 }
105
106 template <typename T>
107 Scavenger<T>::~Scavenger()
108 {
109 if (m_scavenged < m_claimed) {
110 for (size_t i = 0; i < m_objects.size(); ++i) {
111 ObjectTimePair &pair = m_objects[i];
112 if (pair.first != 0) {
113 T *ot = pair.first;
114 pair.first = 0;
115 delete ot;
116 ++m_scavenged;
117 }
118 }
119 }
120
121 clearExcess(0);
122
123 pthread_mutex_destroy(&m_excessMutex);
92 } 124 }
93 125
94 template <typename T> 126 template <typename T>
95 void 127 void
96 Scavenger<T>::claim(T *t) 128 Scavenger<T>::claim(T *t)
109 ++m_claimed; 141 ++m_claimed;
110 return; 142 return;
111 } 143 }
112 } 144 }
113 145
114 // Oh no -- run out of slots! Warn and discard something at 146 std::cerr << "WARNING: Scavenger::claim(" << t << "): run out of slots, "
115 // random (without deleting it -- it's probably safer to leak). 147 << "using non-RT-safe method" << std::endl;
116 148 pushExcess(t);
117 for (size_t i = 0; i < m_objects.size(); ++i) {
118 ObjectTimePair &pair = m_objects[i];
119 if (pair.first != 0) {
120 pair.second = sec;
121 pair.first = t;
122 ++m_claimed;
123 ++m_scavenged;
124 }
125 }
126 } 149 }
127 150
128 template <typename T> 151 template <typename T>
129 void 152 void
130 Scavenger<T>::scavenge(bool clearNow) 153 Scavenger<T>::scavenge(bool clearNow)
145 pair.first = 0; 168 pair.first = 0;
146 delete ot; 169 delete ot;
147 ++m_scavenged; 170 ++m_scavenged;
148 } 171 }
149 } 172 }
173
174 if (sec > m_lastExcess + m_sec) {
175 clearExcess(sec);
176 }
177 }
178
179 template <typename T>
180 void
181 Scavenger<T>::pushExcess(T *t)
182 {
183 pthread_mutex_lock(&m_excessMutex);
184 m_excess.push_back(t);
185 struct timeval tv;
186 (void)gettimeofday(&tv, 0);
187 m_lastExcess = tv.tv_sec;
188 pthread_mutex_unlock(&m_excessMutex);
189 }
190
191 template <typename T>
192 void
193 Scavenger<T>::clearExcess(int sec)
194 {
195 pthread_mutex_lock(&m_excessMutex);
196 for (typename ObjectList::iterator i = m_excess.begin();
197 i != m_excess.end(); ++i) {
198 delete *i;
199 }
200 m_excess.clear();
201 m_lastExcess = sec;
202 pthread_mutex_unlock(&m_excessMutex);
150 } 203 }
151 204
152 #endif 205 #endif