Mercurial > hg > svcore
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 |