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