annotate base/Scavenger.h @ 0:da6937383da8

initial import
author Chris Cannam
date Tue, 10 Jan 2006 16:33:16 +0000
parents
children d86891498eef
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@0 4 A waveform viewer and audio annotation editor.
Chris@0 5 Chris Cannam, Queen Mary University of London, 2005
Chris@0 6
Chris@0 7 This is experimental software. Not for distribution.
Chris@0 8 */
Chris@0 9
Chris@0 10 /*
Chris@0 11 This is a modified version of a source file from the
Chris@0 12 Rosegarden MIDI and audio sequencer and notation editor.
Chris@0 13 This file copyright 2000-2005 Chris Cannam.
Chris@0 14 */
Chris@0 15
Chris@0 16 #ifndef _SCAVENGER_H_
Chris@0 17 #define _SCAVENGER_H_
Chris@0 18
Chris@0 19 #include "System.h"
Chris@0 20
Chris@0 21 #include <vector>
Chris@0 22 #include <sys/time.h>
Chris@0 23
Chris@0 24 /**
Chris@0 25 * A very simple class that facilitates running things like plugins
Chris@0 26 * without locking, by collecting unwanted objects and deleting them
Chris@0 27 * after a delay so as to be sure nobody's in the middle of using
Chris@0 28 * them. Requires scavenge() to be called regularly from a non-RT
Chris@0 29 * thread.
Chris@0 30 *
Chris@0 31 * This is currently not at all suitable for large numbers of objects
Chris@0 32 * -- it's just a quick hack for use with things like plugins.
Chris@0 33 */
Chris@0 34
Chris@0 35 template <typename T>
Chris@0 36 class Scavenger
Chris@0 37 {
Chris@0 38 public:
Chris@0 39 Scavenger(int sec = 2, int defaultObjectListSize = 200);
Chris@0 40
Chris@0 41 /**
Chris@0 42 * Call from an RT thread etc., to pass ownership of t to us.
Chris@0 43 * Only one thread should be calling this on any given scavenger.
Chris@0 44 */
Chris@0 45 void claim(T *t);
Chris@0 46
Chris@0 47 /**
Chris@0 48 * Call from a non-RT thread.
Chris@0 49 * Only one thread should be calling this on any given scavenger.
Chris@0 50 */
Chris@0 51 void scavenge();
Chris@0 52
Chris@0 53 protected:
Chris@0 54 typedef std::pair<T *, int> ObjectTimePair;
Chris@0 55 typedef std::vector<ObjectTimePair> ObjectTimeList;
Chris@0 56 ObjectTimeList m_objects;
Chris@0 57 int m_sec;
Chris@0 58
Chris@0 59 unsigned int m_claimed;
Chris@0 60 unsigned int m_scavenged;
Chris@0 61 };
Chris@0 62
Chris@0 63 /**
Chris@0 64 * A wrapper to permit arrays to be scavenged.
Chris@0 65 */
Chris@0 66
Chris@0 67 template <typename T>
Chris@0 68 class ScavengerArrayWrapper
Chris@0 69 {
Chris@0 70 public:
Chris@0 71 ScavengerArrayWrapper(T *array) : m_array(array) { }
Chris@0 72 ~ScavengerArrayWrapper() { delete[] m_array; }
Chris@0 73
Chris@0 74 private:
Chris@0 75 T *m_array;
Chris@0 76 };
Chris@0 77
Chris@0 78
Chris@0 79 template <typename T>
Chris@0 80 Scavenger<T>::Scavenger(int sec, int defaultObjectListSize) :
Chris@0 81 m_objects(ObjectTimeList(defaultObjectListSize)),
Chris@0 82 m_sec(sec),
Chris@0 83 m_claimed(0),
Chris@0 84 m_scavenged(0)
Chris@0 85 {
Chris@0 86 }
Chris@0 87
Chris@0 88 template <typename T>
Chris@0 89 void
Chris@0 90 Scavenger<T>::claim(T *t)
Chris@0 91 {
Chris@0 92 // std::cerr << "Scavenger::claim(" << t << ")" << std::endl;
Chris@0 93
Chris@0 94 struct timeval tv;
Chris@0 95 (void)gettimeofday(&tv, 0);
Chris@0 96 int sec = tv.tv_sec;
Chris@0 97
Chris@0 98 for (size_t i = 0; i < m_objects.size(); ++i) {
Chris@0 99 ObjectTimePair &pair = m_objects[i];
Chris@0 100 if (pair.first == 0) {
Chris@0 101 pair.second = sec;
Chris@0 102 pair.first = t;
Chris@0 103 ++m_claimed;
Chris@0 104 return;
Chris@0 105 }
Chris@0 106 }
Chris@0 107
Chris@0 108 // Oh no -- run out of slots! Warn and discard something at
Chris@0 109 // random (without deleting it -- it's probably safer to leak).
Chris@0 110
Chris@0 111 for (size_t i = 0; i < m_objects.size(); ++i) {
Chris@0 112 ObjectTimePair &pair = m_objects[i];
Chris@0 113 if (pair.first != 0) {
Chris@0 114 pair.second = sec;
Chris@0 115 pair.first = t;
Chris@0 116 ++m_claimed;
Chris@0 117 ++m_scavenged;
Chris@0 118 }
Chris@0 119 }
Chris@0 120 }
Chris@0 121
Chris@0 122 template <typename T>
Chris@0 123 void
Chris@0 124 Scavenger<T>::scavenge()
Chris@0 125 {
Chris@0 126 // std::cerr << "Scavenger::scavenge: scavenged " << m_scavenged << ", claimed " << m_claimed << std::endl;
Chris@0 127
Chris@0 128 if (m_scavenged >= m_claimed) return;
Chris@0 129
Chris@0 130 struct timeval tv;
Chris@0 131 (void)gettimeofday(&tv, 0);
Chris@0 132 int sec = tv.tv_sec;
Chris@0 133
Chris@0 134 for (size_t i = 0; i < m_objects.size(); ++i) {
Chris@0 135 ObjectTimePair &pair = m_objects[i];
Chris@0 136 if (pair.first != 0 && pair.second + m_sec < sec) {
Chris@0 137 T *ot = pair.first;
Chris@0 138 pair.first = 0;
Chris@0 139 delete ot;
Chris@0 140 ++m_scavenged;
Chris@0 141 }
Chris@0 142 }
Chris@0 143 }
Chris@0 144
Chris@0 145 #endif