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 SV_SCAVENGER_H
23 #define SV_SCAVENGER_H
24 
25 #include "system/System.h"
26 
27 #include <vector>
28 #include <list>
29 #include <QMutex>
30 #include <iostream>
31 
43 template <typename T>
44 class Scavenger
45 {
46 public:
47  Scavenger(int sec = 2, int defaultObjectListSize = 200);
48  ~Scavenger();
49 
54  void claim(T *t);
55 
60  void scavenge(bool clearNow = false);
61 
62 protected:
63  typedef std::pair<T *, time_t> ObjectTimePair;
64  typedef std::vector<ObjectTimePair> ObjectTimeList;
65  ObjectTimeList m_objects;
66  time_t m_sec;
67 
68  typedef std::list<T *> ObjectList;
69  ObjectList m_excess;
70  time_t m_lastExcess;
71  QMutex m_excessMutex;
72  void pushExcess(T *);
73  void clearExcess(time_t);
74 
75  unsigned int m_claimed;
76  unsigned int m_scavenged;
77 };
78 
83 template <typename T>
85 {
86 public:
87  ScavengerArrayWrapper(T *array) : m_array(array) { }
88  ~ScavengerArrayWrapper() { delete[] m_array; }
89 
90 private:
91  T *m_array;
92 };
93 
94 
95 template <typename T>
96 Scavenger<T>::Scavenger(int sec, int defaultObjectListSize) :
97  m_objects(ObjectTimeList(defaultObjectListSize)),
98  m_sec(sec),
99  m_lastExcess(0),
100  m_claimed(0),
101  m_scavenged(0)
102 {
103 }
104 
105 template <typename T>
107 {
108  if (m_scavenged < m_claimed) {
109  for (size_t i = 0; i < m_objects.size(); ++i) {
110  ObjectTimePair &pair = m_objects[i];
111  if (pair.first != 0) {
112  T *ot = pair.first;
113  pair.first = 0;
114  delete ot;
115  ++m_scavenged;
116  }
117  }
118  }
119 
120  clearExcess(0);
121 }
122 
123 template <typename T>
124 void
126 {
127 // std::cerr << "Scavenger::claim(" << t << ")" << std::endl;
128 
129  struct timeval tv;
130  (void)gettimeofday(&tv, 0);
131  time_t sec = tv.tv_sec;
132 
133  for (size_t i = 0; i < m_objects.size(); ++i) {
134  ObjectTimePair &pair = m_objects[i];
135  if (pair.first == 0) {
136  pair.second = sec;
137  pair.first = t;
138  ++m_claimed;
139  return;
140  }
141  }
142 
143  std::cerr << "WARNING: Scavenger::claim(" << t << "): run out of slots, "
144  << "using non-RT-safe method" << std::endl;
145  pushExcess(t);
146 }
147 
148 template <typename T>
149 void
151 {
152 // std::cerr << "Scavenger::scavenge: scavenged " << m_scavenged << ", claimed " << m_claimed << std::endl;
153 
154  if (m_scavenged >= m_claimed) return;
155 
156  struct timeval tv;
157  (void)gettimeofday(&tv, 0);
158  time_t sec = tv.tv_sec;
159 
160  for (size_t i = 0; i < m_objects.size(); ++i) {
161  ObjectTimePair &pair = m_objects[i];
162  if (clearNow ||
163  (pair.first != 0 && pair.second + m_sec < sec)) {
164  T *ot = pair.first;
165  pair.first = 0;
166  delete ot;
167  ++m_scavenged;
168  }
169  }
170 
171  if (sec > m_lastExcess + m_sec) {
172  clearExcess(sec);
173  }
174 }
175 
176 template <typename T>
177 void
179 {
180  m_excessMutex.lock();
181  m_excess.push_back(t);
182  struct timeval tv;
183  (void)gettimeofday(&tv, 0);
184  m_lastExcess = tv.tv_sec;
185  m_excessMutex.unlock();
186 }
187 
188 template <typename T>
189 void
191 {
192  m_excessMutex.lock();
193  for (typename ObjectList::iterator i = m_excess.begin();
194  i != m_excess.end(); ++i) {
195  delete *i;
196  }
197  m_excess.clear();
198  m_lastExcess = sec;
199  m_excessMutex.unlock();
200 }
201 
202 #endif
QMutex m_excessMutex
Definition: Scavenger.h:71
Scavenger(int sec=2, int defaultObjectListSize=200)
Definition: Scavenger.h:96
std::list< T * > ObjectList
Definition: Scavenger.h:68
unsigned int m_claimed
Definition: Scavenger.h:75
time_t m_lastExcess
Definition: Scavenger.h:70
void clearExcess(time_t)
Definition: Scavenger.h:190
ScavengerArrayWrapper(T *array)
Definition: Scavenger.h:87
unsigned int m_scavenged
Definition: Scavenger.h:76
A very simple class that facilitates running things like plugins without locking, by collecting unwan...
Definition: Scavenger.h:44
void scavenge(bool clearNow=false)
Call from a non-RT thread.
Definition: Scavenger.h:150
ObjectTimeList m_objects
Definition: Scavenger.h:65
void pushExcess(T *)
Definition: Scavenger.h:178
A wrapper to permit arrays to be scavenged.
Definition: Scavenger.h:84
std::pair< T *, time_t > ObjectTimePair
Definition: Scavenger.h:63
ObjectList m_excess
Definition: Scavenger.h:69
std::vector< ObjectTimePair > ObjectTimeList
Definition: Scavenger.h:64
~Scavenger()
Definition: Scavenger.h:106
void claim(T *t)
Call from an RT thread etc., to pass ownership of t to us.
Definition: Scavenger.h:125
time_t m_sec
Definition: Scavenger.h:66