Mercurial > hg > svcore
view base/Scavenger.h @ 47:bac8b14ab355
* Add menu for re-adding existing layers
* Fix layer tree window so that it at least approximates correct
* Add bundled operations in command history, for use with things like
multiple consecutive changes to a parameter value
* Disambiguate plugins that happen to have identical descriptions
* Add spectral centroid plugin (could use some parameters!)
* Some other fixes
author | Chris Cannam |
---|---|
date | Fri, 17 Mar 2006 17:38:28 +0000 |
parents | 2fb933f88604 |
children | 39ae3dee27b9 |
line wrap: on
line source
/* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */ /* A waveform viewer and audio annotation editor. Chris Cannam, Queen Mary University of London, 2005-2006 This is experimental software. Not for distribution. */ /* This is a modified version of a source file from the Rosegarden MIDI and audio sequencer and notation editor. This file copyright 2000-2006 Chris Cannam. */ #ifndef _SCAVENGER_H_ #define _SCAVENGER_H_ #include "System.h" #include <vector> #include <sys/time.h> /** * A very simple class that facilitates running things like plugins * without locking, by collecting unwanted objects and deleting them * after a delay so as to be sure nobody's in the middle of using * them. Requires scavenge() to be called regularly from a non-RT * thread. * * This is currently not at all suitable for large numbers of objects * -- it's just a quick hack for use with things like plugins. */ template <typename T> class Scavenger { public: Scavenger(int sec = 2, int defaultObjectListSize = 200); /** * Call from an RT thread etc., to pass ownership of t to us. * Only one thread should be calling this on any given scavenger. */ void claim(T *t); /** * Call from a non-RT thread. * Only one thread should be calling this on any given scavenger. */ void scavenge(bool clearNow = false); protected: typedef std::pair<T *, int> ObjectTimePair; typedef std::vector<ObjectTimePair> ObjectTimeList; ObjectTimeList m_objects; int m_sec; unsigned int m_claimed; unsigned int m_scavenged; }; /** * A wrapper to permit arrays to be scavenged. */ template <typename T> class ScavengerArrayWrapper { public: ScavengerArrayWrapper(T *array) : m_array(array) { } ~ScavengerArrayWrapper() { delete[] m_array; } private: T *m_array; }; template <typename T> Scavenger<T>::Scavenger(int sec, int defaultObjectListSize) : m_objects(ObjectTimeList(defaultObjectListSize)), m_sec(sec), m_claimed(0), m_scavenged(0) { } template <typename T> void Scavenger<T>::claim(T *t) { // std::cerr << "Scavenger::claim(" << t << ")" << std::endl; struct timeval tv; (void)gettimeofday(&tv, 0); int sec = tv.tv_sec; for (size_t i = 0; i < m_objects.size(); ++i) { ObjectTimePair &pair = m_objects[i]; if (pair.first == 0) { pair.second = sec; pair.first = t; ++m_claimed; return; } } // Oh no -- run out of slots! Warn and discard something at // random (without deleting it -- it's probably safer to leak). for (size_t i = 0; i < m_objects.size(); ++i) { ObjectTimePair &pair = m_objects[i]; if (pair.first != 0) { pair.second = sec; pair.first = t; ++m_claimed; ++m_scavenged; } } } template <typename T> void Scavenger<T>::scavenge(bool clearNow) { // std::cerr << "Scavenger::scavenge: scavenged " << m_scavenged << ", claimed " << m_claimed << std::endl; if (m_scavenged >= m_claimed) return; struct timeval tv; (void)gettimeofday(&tv, 0); int sec = tv.tv_sec; for (size_t i = 0; i < m_objects.size(); ++i) { ObjectTimePair &pair = m_objects[i]; if (clearNow || (pair.first != 0 && pair.second + m_sec < sec)) { T *ot = pair.first; pair.first = 0; delete ot; ++m_scavenged; } } } #endif