Mercurial > hg > svcore
diff base/Scavenger.h @ 158:74abef65711b
* Fixes pulled across from Rosegarden
author | Chris Cannam |
---|---|
date | Wed, 16 Aug 2006 14:57:22 +0000 |
parents | 4b2ea82fd0ed |
children | 0e266fa2510f |
line wrap: on
line diff
--- a/base/Scavenger.h Fri Aug 04 17:01:37 2006 +0000 +++ b/base/Scavenger.h Wed Aug 16 14:57:22 2006 +0000 @@ -25,7 +25,10 @@ #include "system/System.h" #include <vector> +#include <list> #include <sys/time.h> +#include <pthread.h> +#include <iostream> /** * A very simple class that facilitates running things like plugins @@ -43,6 +46,7 @@ { public: Scavenger(int sec = 2, int defaultObjectListSize = 200); + ~Scavenger(); /** * Call from an RT thread etc., to pass ownership of t to us. @@ -62,6 +66,13 @@ ObjectTimeList m_objects; int m_sec; + typedef std::list<T *> ObjectList; + ObjectList m_excess; + int m_lastExcess; + pthread_mutex_t m_excessMutex; + void pushExcess(T *); + void clearExcess(int); + unsigned int m_claimed; unsigned int m_scavenged; }; @@ -89,6 +100,27 @@ m_claimed(0), m_scavenged(0) { + pthread_mutex_init(&m_excessMutex, NULL); +} + +template <typename T> +Scavenger<T>::~Scavenger() +{ + if (m_scavenged < m_claimed) { + for (size_t i = 0; i < m_objects.size(); ++i) { + ObjectTimePair &pair = m_objects[i]; + if (pair.first != 0) { + T *ot = pair.first; + pair.first = 0; + delete ot; + ++m_scavenged; + } + } + } + + clearExcess(0); + + pthread_mutex_destroy(&m_excessMutex); } template <typename T> @@ -111,18 +143,9 @@ } } - // 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; - } - } + std::cerr << "WARNING: Scavenger::claim(" << t << "): run out of slots, " + << "using non-RT-safe method" << std::endl; + pushExcess(t); } template <typename T> @@ -147,6 +170,36 @@ ++m_scavenged; } } + + if (sec > m_lastExcess + m_sec) { + clearExcess(sec); + } +} + +template <typename T> +void +Scavenger<T>::pushExcess(T *t) +{ + pthread_mutex_lock(&m_excessMutex); + m_excess.push_back(t); + struct timeval tv; + (void)gettimeofday(&tv, 0); + m_lastExcess = tv.tv_sec; + pthread_mutex_unlock(&m_excessMutex); +} + +template <typename T> +void +Scavenger<T>::clearExcess(int sec) +{ + pthread_mutex_lock(&m_excessMutex); + for (typename ObjectList::iterator i = m_excess.begin(); + i != m_excess.end(); ++i) { + delete *i; + } + m_excess.clear(); + m_lastExcess = sec; + pthread_mutex_unlock(&m_excessMutex); } #endif