From 94cf94718e71bd14fabdb4b2037efeaf2be917ec Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sun, 17 Apr 2016 09:54:14 -0400 Subject: [PATCH] Redefine ODLocker as movable, and it may try-lock only. --- src/FileFormats.h | 4 +--- src/WaveClip.cpp | 8 ++++---- src/ondemand/ODManager.cpp | 2 +- src/ondemand/ODTaskThread.h | 40 +++++++++++++++++++++++++++---------- 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/FileFormats.h b/src/FileFormats.h index 89e7cff07..46787122f 100644 --- a/src/FileFormats.h +++ b/src/FileFormats.h @@ -118,13 +118,11 @@ OSType sf_header_mactype(int format); // This function wrapper uses a mutex to serialize calls to the SndFile library. #include "MemoryX.h" #include "ondemand/ODTaskThread.h" -class ODLock; -class ODLocker; extern ODLock libSndFileMutex; template inline R SFCall(F fun, Args&&... args) { - ODLocker locker{ libSndFileMutex }; + ODLocker locker{ &libSndFileMutex }; return fun(std::forward(args)...); } diff --git a/src/WaveClip.cpp b/src/WaveClip.cpp index 227282b9a..40e38ccf8 100644 --- a/src/WaveClip.cpp +++ b/src/WaveClip.cpp @@ -135,7 +135,7 @@ public: invalEnd = len; - ODLocker locker(mRegionsMutex); + ODLocker locker(&mRegionsMutex); //look thru the region array for a place to insert. We could make this more spiffy than a linear search //but right now it is not needed since there will usually only be one region (which grows) for OD loading. @@ -420,7 +420,7 @@ bool WaveClip::AfterClip(double t) const ///Delete the wave cache - force redraw. Thread-safe void WaveClip::DeleteWaveCache() { - ODLocker locker(mWaveCacheMutex); + ODLocker locker(&mWaveCacheMutex); if(mWaveCache!=NULL) delete mWaveCache; mWaveCache = new WaveCache(); @@ -429,7 +429,7 @@ void WaveClip::DeleteWaveCache() ///Adds an invalid region to the wavecache so it redraws that portion only. void WaveClip::AddInvalidRegion(long startSample, long endSample) { - ODLocker locker(mWaveCacheMutex); + ODLocker locker(&mWaveCacheMutex); if(mWaveCache!=NULL) mWaveCache->AddInvalidRegion(startSample,endSample); } @@ -525,7 +525,7 @@ bool WaveClip::GetWaveDisplay(WaveDisplay &display, double t0, } else { // Lock the list of invalid regions - ODLocker locker(mWaveCacheMutex); + ODLocker locker(&mWaveCacheMutex); const double tstep = 1.0 / pixelsPerSecond; const double samplesPerPixel = mRate * tstep; diff --git a/src/ondemand/ODManager.cpp b/src/ondemand/ODManager.cpp index 4684d7e70..2c9c00fd2 100644 --- a/src/ondemand/ODManager.cpp +++ b/src/ondemand/ODManager.cpp @@ -277,7 +277,7 @@ void ODManager::Start() // JKC: If there are no tasks ready to run, or we're paused then // we wait for there to be tasks in the queue. { - ODLocker locker{ mQueueNotEmptyCondLock }; + ODLocker locker{ &mQueueNotEmptyCondLock }; if( (!tasksInArray) || paused) mQueueNotEmptyCond->Wait(); } diff --git a/src/ondemand/ODTaskThread.h b/src/ondemand/ODTaskThread.h index 94ef10732..dd08a7b79 100644 --- a/src/ondemand/ODTaskThread.h +++ b/src/ondemand/ODTaskThread.h @@ -24,6 +24,7 @@ #include #include "../Audacity.h" // contains the set-up of AUDACITY_DLL_API +#include "../MemoryX.h" class ODTask; @@ -170,25 +171,44 @@ protected: #endif // __WXMAC__ -// Like wxMutexLocker +// class ODLocker // So you can use the RAII idiom with ODLock, on whatever platform -class ODLocker -{ +// Construct with pointer to the lock, or default-construct and later +// reset() +// If constructed with only a try-lock, and the lock was not acquired, +// then it returns false when cast to bool +struct ODUnlocker { void operator () (ODLock *p) const { if(p) p->Unlock(); } }; +using ODLockerBase = std::unique_ptr; +class ODLocker : public ODLockerBase { public: - ODLocker(ODLock &lock) - : mLock(lock) + // Lock any bare pointer to ODLock at construction time or when resetting. + explicit ODLocker(ODLock *p = nullptr, bool tryOnly = false) { - mLock.Lock(); + reset(p, tryOnly); } - ~ODLocker() + void reset(ODLock *p = nullptr, bool tryOnly = false) { - mLock.Unlock(); + ODLockerBase::reset(p); + if(p) { + if (tryOnly) { + if (p->TryLock() != 0) + ODLockerBase::reset(nullptr); + } + else + p->Lock(); + } } -private: + // Assume already locked when moving ODLocker. Don't lock again. + ODLocker(ODLocker&& that) : ODLockerBase { std::move(that) } {} + ODLocker &operator= (ODLocker && that) { + ODLockerBase::operator= ( std::move(that) ); + return *this; + } - ODLock &mLock; + ODLocker(const ODLocker &that) PROHIBITED; + ODLocker &operator= (const ODLocker &that) PROHIBITED; }; #endif //__AUDACITY_ODTASKTHREAD__