annotate base/Scavenger.h @ 282:d9319859a4cf tip

(none)
author benoitrigolleau
date Fri, 31 Oct 2008 11:00:24 +0000
parents fc9323a41f5a
children
rev   line source
lbajardsilogic@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
lbajardsilogic@0 2
lbajardsilogic@0 3 /*
lbajardsilogic@0 4 Sonic Visualiser
lbajardsilogic@0 5 An audio file viewer and annotation editor.
lbajardsilogic@0 6 Centre for Digital Music, Queen Mary, University of London.
lbajardsilogic@0 7 This file copyright 2006 Chris Cannam.
lbajardsilogic@0 8
lbajardsilogic@0 9 This program is free software; you can redistribute it and/or
lbajardsilogic@0 10 modify it under the terms of the GNU General Public License as
lbajardsilogic@0 11 published by the Free Software Foundation; either version 2 of the
lbajardsilogic@0 12 License, or (at your option) any later version. See the file
lbajardsilogic@0 13 COPYING included with this distribution for more information.
lbajardsilogic@0 14 */
lbajardsilogic@0 15
lbajardsilogic@0 16 /*
lbajardsilogic@0 17 This is a modified version of a source file from the
lbajardsilogic@0 18 Rosegarden MIDI and audio sequencer and notation editor.
lbajardsilogic@0 19 This file copyright 2000-2006 Chris Cannam.
lbajardsilogic@0 20 */
lbajardsilogic@0 21
lbajardsilogic@0 22 #ifndef _SCAVENGER_H_
lbajardsilogic@0 23 #define _SCAVENGER_H_
lbajardsilogic@0 24
lbajardsilogic@0 25 #include "system/System.h"
lbajardsilogic@0 26
lbajardsilogic@0 27 #include <vector>
lbajardsilogic@0 28 #include <list>
lbajardsilogic@0 29 //#include <sys/time.h>
lbajardsilogic@0 30 #include <QMutex>
lbajardsilogic@0 31 #include <iostream>
lbajardsilogic@0 32
lbajardsilogic@0 33 /**
lbajardsilogic@0 34 * A very simple class that facilitates running things like plugins
lbajardsilogic@0 35 * without locking, by collecting unwanted objects and deleting them
lbajardsilogic@0 36 * after a delay so as to be sure nobody's in the middle of using
lbajardsilogic@0 37 * them. Requires scavenge() to be called regularly from a non-RT
lbajardsilogic@0 38 * thread.
lbajardsilogic@0 39 *
lbajardsilogic@0 40 * This is currently not at all suitable for large numbers of objects
lbajardsilogic@0 41 * -- it's just a quick hack for use with things like plugins.
lbajardsilogic@0 42 */
lbajardsilogic@0 43
lbajardsilogic@0 44 template <typename T>
lbajardsilogic@0 45 class Scavenger
lbajardsilogic@0 46 {
lbajardsilogic@0 47 public:
lbajardsilogic@0 48 Scavenger(int sec = 2, int defaultObjectListSize = 200);
lbajardsilogic@0 49 ~Scavenger();
lbajardsilogic@0 50
lbajardsilogic@0 51 /**
lbajardsilogic@0 52 * Call from an RT thread etc., to pass ownership of t to us.
lbajardsilogic@0 53 * Only one thread should be calling this on any given scavenger.
lbajardsilogic@0 54 */
lbajardsilogic@0 55 void claim(T *t);
lbajardsilogic@0 56
lbajardsilogic@0 57 /**
lbajardsilogic@0 58 * Call from a non-RT thread.
lbajardsilogic@0 59 * Only one thread should be calling this on any given scavenger.
lbajardsilogic@0 60 */
lbajardsilogic@0 61 void scavenge(bool clearNow = false);
lbajardsilogic@0 62
lbajardsilogic@0 63 protected:
lbajardsilogic@0 64 typedef std::pair<T *, int> ObjectTimePair;
lbajardsilogic@0 65 typedef std::vector<ObjectTimePair> ObjectTimeList;
lbajardsilogic@0 66 ObjectTimeList m_objects;
lbajardsilogic@0 67 int m_sec;
lbajardsilogic@0 68
lbajardsilogic@0 69 typedef std::list<T *> ObjectList;
lbajardsilogic@0 70 ObjectList m_excess;
lbajardsilogic@0 71 int m_lastExcess;
lbajardsilogic@0 72 QMutex m_excessMutex;
lbajardsilogic@0 73 void pushExcess(T *);
lbajardsilogic@0 74 void clearExcess(int);
lbajardsilogic@0 75
lbajardsilogic@0 76 unsigned int m_claimed;
lbajardsilogic@0 77 unsigned int m_scavenged;
lbajardsilogic@0 78 };
lbajardsilogic@0 79
lbajardsilogic@0 80 /**
lbajardsilogic@0 81 * A wrapper to permit arrays to be scavenged.
lbajardsilogic@0 82 */
lbajardsilogic@0 83
lbajardsilogic@0 84 template <typename T>
lbajardsilogic@0 85 class ScavengerArrayWrapper
lbajardsilogic@0 86 {
lbajardsilogic@0 87 public:
lbajardsilogic@0 88 ScavengerArrayWrapper(T *array) : m_array(array) { }
lbajardsilogic@0 89 ~ScavengerArrayWrapper() { delete[] m_array; }
lbajardsilogic@0 90
lbajardsilogic@0 91 private:
lbajardsilogic@0 92 T *m_array;
lbajardsilogic@0 93 };
lbajardsilogic@0 94
lbajardsilogic@0 95
lbajardsilogic@0 96 template <typename T>
lbajardsilogic@0 97 Scavenger<T>::Scavenger(int sec, int defaultObjectListSize) :
lbajardsilogic@0 98 m_objects(ObjectTimeList(defaultObjectListSize)),
lbajardsilogic@0 99 m_sec(sec),
lbajardsilogic@0 100 m_lastExcess(0),
lbajardsilogic@0 101 m_claimed(0),
lbajardsilogic@0 102 m_scavenged(0)
lbajardsilogic@0 103 {
lbajardsilogic@0 104 }
lbajardsilogic@0 105
lbajardsilogic@0 106 template <typename T>
lbajardsilogic@0 107 Scavenger<T>::~Scavenger()
lbajardsilogic@0 108 {
lbajardsilogic@0 109 if (m_scavenged < m_claimed) {
lbajardsilogic@0 110 for (size_t i = 0; i < m_objects.size(); ++i) {
lbajardsilogic@0 111 ObjectTimePair &pair = m_objects[i];
lbajardsilogic@0 112 if (pair.first != 0) {
lbajardsilogic@0 113 T *ot = pair.first;
lbajardsilogic@0 114 pair.first = 0;
lbajardsilogic@0 115 delete ot;
lbajardsilogic@0 116 ++m_scavenged;
lbajardsilogic@0 117 }
lbajardsilogic@0 118 }
lbajardsilogic@0 119 }
lbajardsilogic@0 120
lbajardsilogic@0 121 clearExcess(0);
lbajardsilogic@0 122 }
lbajardsilogic@0 123
lbajardsilogic@0 124 template <typename T>
lbajardsilogic@0 125 void
lbajardsilogic@0 126 Scavenger<T>::claim(T *t)
lbajardsilogic@0 127 {
lbajardsilogic@0 128 // std::cerr << "Scavenger::claim(" << t << ")" << std::endl;
lbajardsilogic@0 129
lbajardsilogic@0 130 struct timeval tv;
lbajardsilogic@0 131 (void)gettimeofday(&tv, 0);
lbajardsilogic@0 132 int sec = tv.tv_sec;
lbajardsilogic@0 133
lbajardsilogic@0 134 for (size_t i = 0; i < m_objects.size(); ++i) {
lbajardsilogic@0 135 ObjectTimePair &pair = m_objects[i];
lbajardsilogic@0 136 if (pair.first == 0) {
lbajardsilogic@0 137 pair.second = sec;
lbajardsilogic@0 138 pair.first = t;
lbajardsilogic@0 139 ++m_claimed;
lbajardsilogic@0 140 return;
lbajardsilogic@0 141 }
lbajardsilogic@0 142 }
lbajardsilogic@0 143
lbajardsilogic@0 144 std::cerr << "WARNING: Scavenger::claim(" << t << "): run out of slots, "
lbajardsilogic@0 145 << "using non-RT-safe method" << std::endl;
lbajardsilogic@0 146 pushExcess(t);
lbajardsilogic@0 147 }
lbajardsilogic@0 148
lbajardsilogic@0 149 template <typename T>
lbajardsilogic@0 150 void
lbajardsilogic@0 151 Scavenger<T>::scavenge(bool clearNow)
lbajardsilogic@0 152 {
lbajardsilogic@0 153 // std::cerr << "Scavenger::scavenge: scavenged " << m_scavenged << ", claimed " << m_claimed << std::endl;
lbajardsilogic@0 154
lbajardsilogic@0 155 if (m_scavenged >= m_claimed) return;
lbajardsilogic@0 156
lbajardsilogic@0 157 struct timeval tv;
lbajardsilogic@0 158 (void)gettimeofday(&tv, 0);
lbajardsilogic@0 159 int sec = tv.tv_sec;
lbajardsilogic@0 160
lbajardsilogic@0 161 for (size_t i = 0; i < m_objects.size(); ++i) {
lbajardsilogic@0 162 ObjectTimePair &pair = m_objects[i];
lbajardsilogic@0 163 if (clearNow ||
lbajardsilogic@0 164 (pair.first != 0 && pair.second + m_sec < sec)) {
lbajardsilogic@0 165 T *ot = pair.first;
lbajardsilogic@0 166 pair.first = 0;
lbajardsilogic@0 167 delete ot;
lbajardsilogic@0 168 ++m_scavenged;
lbajardsilogic@0 169 }
lbajardsilogic@0 170 }
lbajardsilogic@0 171
lbajardsilogic@0 172 if (sec > m_lastExcess + m_sec) {
lbajardsilogic@0 173 clearExcess(sec);
lbajardsilogic@0 174 }
lbajardsilogic@0 175 }
lbajardsilogic@0 176
lbajardsilogic@0 177 template <typename T>
lbajardsilogic@0 178 void
lbajardsilogic@0 179 Scavenger<T>::pushExcess(T *t)
lbajardsilogic@0 180 {
lbajardsilogic@0 181 m_excessMutex.lock();
lbajardsilogic@0 182 m_excess.push_back(t);
lbajardsilogic@0 183 struct timeval tv;
lbajardsilogic@0 184 (void)gettimeofday(&tv, 0);
lbajardsilogic@0 185 m_lastExcess = tv.tv_sec;
lbajardsilogic@0 186 m_excessMutex.unlock();
lbajardsilogic@0 187 }
lbajardsilogic@0 188
lbajardsilogic@0 189 template <typename T>
lbajardsilogic@0 190 void
lbajardsilogic@0 191 Scavenger<T>::clearExcess(int sec)
lbajardsilogic@0 192 {
lbajardsilogic@0 193 m_excessMutex.lock();
lbajardsilogic@0 194 for (typename ObjectList::iterator i = m_excess.begin();
lbajardsilogic@0 195 i != m_excess.end(); ++i) {
lbajardsilogic@0 196 delete *i;
lbajardsilogic@0 197 }
lbajardsilogic@0 198 m_excess.clear();
lbajardsilogic@0 199 m_lastExcess = sec;
lbajardsilogic@0 200 m_excessMutex.unlock();
lbajardsilogic@0 201 }
lbajardsilogic@0 202
lbajardsilogic@0 203 #endif