Mercurial > hg > svcore
comparison base/Scavenger.h @ 0:da6937383da8
initial import
author | Chris Cannam |
---|---|
date | Tue, 10 Jan 2006 16:33:16 +0000 |
parents | |
children | d86891498eef |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:da6937383da8 |
---|---|
1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 A waveform viewer and audio annotation editor. | |
5 Chris Cannam, Queen Mary University of London, 2005 | |
6 | |
7 This is experimental software. Not for distribution. | |
8 */ | |
9 | |
10 /* | |
11 This is a modified version of a source file from the | |
12 Rosegarden MIDI and audio sequencer and notation editor. | |
13 This file copyright 2000-2005 Chris Cannam. | |
14 */ | |
15 | |
16 #ifndef _SCAVENGER_H_ | |
17 #define _SCAVENGER_H_ | |
18 | |
19 #include "System.h" | |
20 | |
21 #include <vector> | |
22 #include <sys/time.h> | |
23 | |
24 /** | |
25 * A very simple class that facilitates running things like plugins | |
26 * without locking, by collecting unwanted objects and deleting them | |
27 * after a delay so as to be sure nobody's in the middle of using | |
28 * them. Requires scavenge() to be called regularly from a non-RT | |
29 * thread. | |
30 * | |
31 * This is currently not at all suitable for large numbers of objects | |
32 * -- it's just a quick hack for use with things like plugins. | |
33 */ | |
34 | |
35 template <typename T> | |
36 class Scavenger | |
37 { | |
38 public: | |
39 Scavenger(int sec = 2, int defaultObjectListSize = 200); | |
40 | |
41 /** | |
42 * Call from an RT thread etc., to pass ownership of t to us. | |
43 * Only one thread should be calling this on any given scavenger. | |
44 */ | |
45 void claim(T *t); | |
46 | |
47 /** | |
48 * Call from a non-RT thread. | |
49 * Only one thread should be calling this on any given scavenger. | |
50 */ | |
51 void scavenge(); | |
52 | |
53 protected: | |
54 typedef std::pair<T *, int> ObjectTimePair; | |
55 typedef std::vector<ObjectTimePair> ObjectTimeList; | |
56 ObjectTimeList m_objects; | |
57 int m_sec; | |
58 | |
59 unsigned int m_claimed; | |
60 unsigned int m_scavenged; | |
61 }; | |
62 | |
63 /** | |
64 * A wrapper to permit arrays to be scavenged. | |
65 */ | |
66 | |
67 template <typename T> | |
68 class ScavengerArrayWrapper | |
69 { | |
70 public: | |
71 ScavengerArrayWrapper(T *array) : m_array(array) { } | |
72 ~ScavengerArrayWrapper() { delete[] m_array; } | |
73 | |
74 private: | |
75 T *m_array; | |
76 }; | |
77 | |
78 | |
79 template <typename T> | |
80 Scavenger<T>::Scavenger(int sec, int defaultObjectListSize) : | |
81 m_objects(ObjectTimeList(defaultObjectListSize)), | |
82 m_sec(sec), | |
83 m_claimed(0), | |
84 m_scavenged(0) | |
85 { | |
86 } | |
87 | |
88 template <typename T> | |
89 void | |
90 Scavenger<T>::claim(T *t) | |
91 { | |
92 // std::cerr << "Scavenger::claim(" << t << ")" << std::endl; | |
93 | |
94 struct timeval tv; | |
95 (void)gettimeofday(&tv, 0); | |
96 int sec = tv.tv_sec; | |
97 | |
98 for (size_t i = 0; i < m_objects.size(); ++i) { | |
99 ObjectTimePair &pair = m_objects[i]; | |
100 if (pair.first == 0) { | |
101 pair.second = sec; | |
102 pair.first = t; | |
103 ++m_claimed; | |
104 return; | |
105 } | |
106 } | |
107 | |
108 // Oh no -- run out of slots! Warn and discard something at | |
109 // random (without deleting it -- it's probably safer to leak). | |
110 | |
111 for (size_t i = 0; i < m_objects.size(); ++i) { | |
112 ObjectTimePair &pair = m_objects[i]; | |
113 if (pair.first != 0) { | |
114 pair.second = sec; | |
115 pair.first = t; | |
116 ++m_claimed; | |
117 ++m_scavenged; | |
118 } | |
119 } | |
120 } | |
121 | |
122 template <typename T> | |
123 void | |
124 Scavenger<T>::scavenge() | |
125 { | |
126 // std::cerr << "Scavenger::scavenge: scavenged " << m_scavenged << ", claimed " << m_claimed << std::endl; | |
127 | |
128 if (m_scavenged >= m_claimed) return; | |
129 | |
130 struct timeval tv; | |
131 (void)gettimeofday(&tv, 0); | |
132 int sec = tv.tv_sec; | |
133 | |
134 for (size_t i = 0; i < m_objects.size(); ++i) { | |
135 ObjectTimePair &pair = m_objects[i]; | |
136 if (pair.first != 0 && pair.second + m_sec < sec) { | |
137 T *ot = pair.first; | |
138 pair.first = 0; | |
139 delete ot; | |
140 ++m_scavenged; | |
141 } | |
142 } | |
143 } | |
144 | |
145 #endif |