svcore  1.9
Scavenger.h
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7  This file copyright 2006 Chris Cannam.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 /*
17  This is a modified version of a source file from the
18  Rosegarden MIDI and audio sequencer and notation editor.
19  This file copyright 2000-2006 Chris Cannam.
20 */
21 
22 #ifndef _SCAVENGER_H_
23 #define _SCAVENGER_H_
24 
25 #include "system/System.h"
26 
27 #include <vector>
28 #include <list>
29 #include <sys/time.h>
30 #include <QMutex>
31 #include <iostream>
32 
44 template <typename T>
45 class Scavenger
46 {
47 public:
48  Scavenger(int sec = 2, int defaultObjectListSize = 200);
49  ~Scavenger();
50 
55  void claim(T *t);
56 
61  void scavenge(bool clearNow = false);
62 
63 protected:
64  typedef std::pair<T *, int> ObjectTimePair;
65  typedef std::vector<ObjectTimePair> ObjectTimeList;
67  int m_sec;
68 
69  typedef std::list<T *> ObjectList;
72  QMutex m_excessMutex;
73  void pushExcess(T *);
74  void clearExcess(int);
75 
76  unsigned int m_claimed;
77  unsigned int m_scavenged;
78 };
79 
84 template <typename T>
86 {
87 public:
88  ScavengerArrayWrapper(T *array) : m_array(array) { }
90 
91 private:
92  T *m_array;
93 };
94 
95 
96 template <typename T>
97 Scavenger<T>::Scavenger(int sec, int defaultObjectListSize) :
98  m_objects(ObjectTimeList(defaultObjectListSize)),
99  m_sec(sec),
100  m_lastExcess(0),
101  m_claimed(0),
102  m_scavenged(0)
103 {
104 }
105 
106 template <typename T>
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 
124 template <typename T>
125 void
127 {
128 // std::cerr << "Scavenger::claim(" << t << ")" << std::endl;
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) {
137  pair.second = sec;
138  pair.first = t;
139  ++m_claimed;
140  return;
141  }
142  }
143 
144  std::cerr << "WARNING: Scavenger::claim(" << t << "): run out of slots, "
145  << "using non-RT-safe method" << std::endl;
146  pushExcess(t);
147 }
148 
149 template <typename T>
150 void
152 {
153 // std::cerr << "Scavenger::scavenge: scavenged " << m_scavenged << ", claimed " << m_claimed << std::endl;
154 
155  if (m_scavenged >= m_claimed) return;
156 
157  struct timeval tv;
158  (void)gettimeofday(&tv, 0);
159  int sec = tv.tv_sec;
160 
161  for (size_t i = 0; i < m_objects.size(); ++i) {
162  ObjectTimePair &pair = m_objects[i];
163  if (clearNow ||
164  (pair.first != 0 && pair.second + m_sec < sec)) {
165  T *ot = pair.first;
166  pair.first = 0;
167  delete ot;
168  ++m_scavenged;
169  }
170  }
171 
172  if (sec > m_lastExcess + m_sec) {
173  clearExcess(sec);
174  }
175 }
176 
177 template <typename T>
178 void
180 {
181  m_excessMutex.lock();
182  m_excess.push_back(t);
183  struct timeval tv;
184  (void)gettimeofday(&tv, 0);
185  m_lastExcess = tv.tv_sec;
186  m_excessMutex.unlock();
187 }
188 
189 template <typename T>
190 void
192 {
193  m_excessMutex.lock();
194  for (typename ObjectList::iterator i = m_excess.begin();
195  i != m_excess.end(); ++i) {
196  delete *i;
197  }
198  m_excess.clear();
199  m_lastExcess = sec;
200  m_excessMutex.unlock();
201 }
202 
203 #endif
QMutex m_excessMutex
Definition: Scavenger.h:72
Scavenger(int sec=2, int defaultObjectListSize=200)
Definition: Scavenger.h:97
std::list< T * > ObjectList
Definition: Scavenger.h:69
unsigned int m_claimed
Definition: Scavenger.h:76
void clearExcess(int)
Definition: Scavenger.h:191
ScavengerArrayWrapper(T *array)
Definition: Scavenger.h:88
unsigned int m_scavenged
Definition: Scavenger.h:77
A very simple class that facilitates running things like plugins without locking, by collecting unwan...
Definition: Scavenger.h:45
void scavenge(bool clearNow=false)
Call from a non-RT thread.
Definition: Scavenger.h:151
ObjectTimeList m_objects
Definition: Scavenger.h:66
int m_lastExcess
Definition: Scavenger.h:71
std::pair< T *, int > ObjectTimePair
Definition: Scavenger.h:64
void pushExcess(T *)
Definition: Scavenger.h:179
A wrapper to permit arrays to be scavenged.
Definition: Scavenger.h:85
ObjectList m_excess
Definition: Scavenger.h:70
std::vector< ObjectTimePair > ObjectTimeList
Definition: Scavenger.h:65
~Scavenger()
Definition: Scavenger.h:107
void claim(T *t)
Call from an RT thread etc., to pass ownership of t to us.
Definition: Scavenger.h:126
int m_sec
Definition: Scavenger.h:67