# HG changeset patch # User Chris Cannam # Date 1155740242 0 # Node ID 74abef65711bfd727362a1f2306d36d1605f4afb # Parent c03ec31005e16c9d3f06bf9abac49eb3ee468f74 * Fixes pulled across from Rosegarden diff -r c03ec31005e1 -r 74abef65711b base/Scavenger.h --- 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 +#include #include +#include +#include /** * 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 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 +Scavenger::~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 @@ -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 @@ -147,6 +170,36 @@ ++m_scavenged; } } + + if (sec > m_lastExcess + m_sec) { + clearExcess(sec); + } +} + +template +void +Scavenger::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 +void +Scavenger::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