annotate base/Scavenger.h @ 76:af2725b5d6fe

* Implement harmonic cursor in spectrogram * Implement layer export. This doesn't quite do the right thing for the SV XML layer export yet -- it doesn't include layer display information, so when imported, it only creates an invisible model. Could also do with fixing CSV file import so as to work correctly for note and text layers.
author Chris Cannam
date Mon, 10 Apr 2006 17:22:59 +0000
parents d397ea0a79f5
children 4b2ea82fd0ed
rev   line source
Chris@49 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@52 4 Sonic Visualiser
Chris@52 5 An audio file viewer and annotation editor.
Chris@52 6 Centre for Digital Music, Queen Mary, University of London.
Chris@52 7 This file copyright 2006 Chris Cannam.
Chris@0 8
Chris@52 9 This program is free software; you can redistribute it and/or
Chris@52 10 modify it under the terms of the GNU General Public License as
Chris@52 11 published by the Free Software Foundation; either version 2 of the
Chris@52 12 License, or (at your option) any later version. See the file
Chris@52 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@0 16 /*
Chris@0 17 This is a modified version of a source file from the
Chris@0 18 Rosegarden MIDI and audio sequencer and notation editor.
Chris@17 19 This file copyright 2000-2006 Chris Cannam.
Chris@0 20 */
Chris@0 21
Chris@0 22 #ifndef _SCAVENGER_H_
Chris@0 23 #define _SCAVENGER_H_
Chris@0 24
Chris@0 25 #include "System.h"
Chris@0 26
Chris@0 27 #include <vector>
Chris@0 28 #include <sys/time.h>
Chris@0 29
Chris@0 30 /**
Chris@0 31 * A very simple class that facilitates running things like plugins
Chris@0 32 * without locking, by collecting unwanted objects and deleting them
Chris@0 33 * after a delay so as to be sure nobody's in the middle of using
Chris@0 34 * them. Requires scavenge() to be called regularly from a non-RT
Chris@0 35 * thread.
Chris@0 36 *
Chris@0 37 * This is currently not at all suitable for large numbers of objects
Chris@0 38 * -- it's just a quick hack for use with things like plugins.
Chris@0 39 */
Chris@0 40
Chris@0 41 template <typename T>
Chris@0 42 class Scavenger
Chris@0 43 {
Chris@0 44 public:
Chris@0 45 Scavenger(int sec = 2, int defaultObjectListSize = 200);
Chris@0 46
Chris@0 47 /**
Chris@0 48 * Call from an RT thread etc., to pass ownership of t to us.
Chris@0 49 * Only one thread should be calling this on any given scavenger.
Chris@0 50 */
Chris@0 51 void claim(T *t);
Chris@0 52
Chris@0 53 /**
Chris@0 54 * Call from a non-RT thread.
Chris@0 55 * Only one thread should be calling this on any given scavenger.
Chris@0 56 */
Chris@14 57 void scavenge(bool clearNow = false);
Chris@0 58
Chris@0 59 protected:
Chris@0 60 typedef std::pair<T *, int> ObjectTimePair;
Chris@0 61 typedef std::vector<ObjectTimePair> ObjectTimeList;
Chris@0 62 ObjectTimeList m_objects;
Chris@0 63 int m_sec;
Chris@0 64
Chris@0 65 unsigned int m_claimed;
Chris@0 66 unsigned int m_scavenged;
Chris@0 67 };
Chris@0 68
Chris@0 69 /**
Chris@0 70 * A wrapper to permit arrays to be scavenged.
Chris@0 71 */
Chris@0 72
Chris@0 73 template <typename T>
Chris@0 74 class ScavengerArrayWrapper
Chris@0 75 {
Chris@0 76 public:
Chris@0 77 ScavengerArrayWrapper(T *array) : m_array(array) { }
Chris@0 78 ~ScavengerArrayWrapper() { delete[] m_array; }
Chris@0 79
Chris@0 80 private:
Chris@0 81 T *m_array;
Chris@0 82 };
Chris@0 83
Chris@0 84
Chris@0 85 template <typename T>
Chris@0 86 Scavenger<T>::Scavenger(int sec, int defaultObjectListSize) :
Chris@0 87 m_objects(ObjectTimeList(defaultObjectListSize)),
Chris@0 88 m_sec(sec),
Chris@0 89 m_claimed(0),
Chris@0 90 m_scavenged(0)
Chris@0 91 {
Chris@0 92 }
Chris@0 93
Chris@0 94 template <typename T>
Chris@0 95 void
Chris@0 96 Scavenger<T>::claim(T *t)
Chris@0 97 {
Chris@0 98 // std::cerr << "Scavenger::claim(" << t << ")" << std::endl;
Chris@0 99
Chris@0 100 struct timeval tv;
Chris@0 101 (void)gettimeofday(&tv, 0);
Chris@0 102 int sec = tv.tv_sec;
Chris@0 103
Chris@0 104 for (size_t i = 0; i < m_objects.size(); ++i) {
Chris@0 105 ObjectTimePair &pair = m_objects[i];
Chris@0 106 if (pair.first == 0) {
Chris@0 107 pair.second = sec;
Chris@0 108 pair.first = t;
Chris@0 109 ++m_claimed;
Chris@0 110 return;
Chris@0 111 }
Chris@0 112 }
Chris@0 113
Chris@0 114 // Oh no -- run out of slots! Warn and discard something at
Chris@0 115 // random (without deleting it -- it's probably safer to leak).
Chris@0 116
Chris@0 117 for (size_t i = 0; i < m_objects.size(); ++i) {
Chris@0 118 ObjectTimePair &pair = m_objects[i];
Chris@0 119 if (pair.first != 0) {
Chris@0 120 pair.second = sec;
Chris@0 121 pair.first = t;
Chris@0 122 ++m_claimed;
Chris@0 123 ++m_scavenged;
Chris@0 124 }
Chris@0 125 }
Chris@0 126 }
Chris@0 127
Chris@0 128 template <typename T>
Chris@0 129 void
Chris@14 130 Scavenger<T>::scavenge(bool clearNow)
Chris@0 131 {
Chris@0 132 // std::cerr << "Scavenger::scavenge: scavenged " << m_scavenged << ", claimed " << m_claimed << std::endl;
Chris@0 133
Chris@0 134 if (m_scavenged >= m_claimed) return;
Chris@0 135
Chris@0 136 struct timeval tv;
Chris@0 137 (void)gettimeofday(&tv, 0);
Chris@0 138 int sec = tv.tv_sec;
Chris@0 139
Chris@0 140 for (size_t i = 0; i < m_objects.size(); ++i) {
Chris@0 141 ObjectTimePair &pair = m_objects[i];
Chris@14 142 if (clearNow ||
Chris@14 143 (pair.first != 0 && pair.second + m_sec < sec)) {
Chris@0 144 T *ot = pair.first;
Chris@0 145 pair.first = 0;
Chris@0 146 delete ot;
Chris@0 147 ++m_scavenged;
Chris@0 148 }
Chris@0 149 }
Chris@0 150 }
Chris@0 151
Chris@0 152 #endif