annotate base/Scavenger.h @ 123:0f37e92e1782

* 1502816 file export is too slow and memory-hungry Use text stream when writing to file instead of accumulating into a string. * 1500625 Auto-align in MIDI layer confusing Make value extents convert to Hz in return value * 1494623: Duplicate display of frame 0 from vamp plugin output
author Chris Cannam
date Thu, 15 Jun 2006 15:48:05 +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