From 1bc81727979399bd654e725ec3f8ff3ebfe96902 Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Sat, 2 Oct 2021 17:39:15 +0100 Subject: [PATCH] Convert OsdVector::PictureReader to std::thread, stop spinning the main loop and only wait on cond --- osdvector.cc | 104 ++++++++++++++++++++++++++++++++------------------- osdvector.h | 10 ++++- vdr.cc | 2 +- 3 files changed, 74 insertions(+), 42 deletions(-) diff --git a/osdvector.cc b/osdvector.cc index 71a6d30..26072c2 100644 --- a/osdvector.cc +++ b/osdvector.cc @@ -906,26 +906,51 @@ ImageIndex OsdVector::getImagePalette(int width, int height, const unsigned char OsdVector::PictureReader::~PictureReader() { - decoders_lock.lock(); + threadMutex.lock(); + if (readerThread.joinable()) + { + threadReqQuit = true; + threadCond.notify_one(); + threadMutex.unlock(); + readerThread.join(); + } + else + threadMutex.unlock(); + + decoders_lock.lock(); while (decoders.size()) { PictureDecoder* dec = decoders.front(); decoders.pop_front(); delete dec; } - decoders_lock.unlock(); } void OsdVector::PictureReader::init() { - threadStart(); + threadMutex.lock(); + readerThread = std::thread( [this] + { + threadMutex.lock(); + threadMutex.unlock(); + threadMethod(); + }); + threadMutex.unlock(); } void OsdVector::PictureReader::shutdown() { - threadStop(); + std::unique_lock lg(threadMutex); + + if (readerThread.joinable()) + { + threadReqQuit = true; + threadCond.notify_one(); + lg.unlock(); + readerThread.join(); + } } void OsdVector::PictureReader::addDecoder(PictureDecoder* decoder) @@ -961,21 +986,26 @@ void OsdVector::PictureReader::removeDecoder(PictureDecoder* decoder) void OsdVector::PictureReader::threadMethod() { OsdVector* osdvector = dynamic_cast(Osd::getInstance()); - LogNT::getInstance()->debug(TAG, "TVMedia Start Picture Reader"); + LogNT::getInstance()->debug("PictureReader", "TVMedia Start Picture Reader"); + + std::unique_lock ul(threadMutex); // locked while (true) { - if (!threadIsActive()) - { - LogNT::getInstance()->debug(TAG, "TVMedia End Picture Reader"); - threadCheckExit(); - } + threadCond.wait(ul, [this]{ return threadReqQuit || runLoop; }); + // locked + if (threadReqQuit) return; // unlock + LogNT::getInstance()->debug("PictureReader", "Running loop"); + runLoop = false; + ul.unlock(); - bool todos = true; + // unlocked while we work - while (todos) + bool miniRunAgain; + do { - todos = false; + miniRunAgain = false; + PictureInfo pictinf; decoders_lock.lock(); std::list::iterator itty = decoders.begin(); @@ -984,38 +1014,20 @@ void OsdVector::PictureReader::threadMethod() { if ((*itty)->getDecodedPicture(pictinf)) // FIXME somewhere around here?, or in getDecodedPicture, try SA optimisation { - todos = true; + miniRunAgain = true; osdvector->createPicture(pictinf); } - itty++; } - if (processReceivedPictures()) - { - todos = true; - } - + if (processReceivedPictures()) miniRunAgain = true; decoders_lock.unlock(); - } - - //LogNT::getInstance()->debug(TAG, "TVMedia Sleep Picture Reader"); - struct timespec target_time; - getClockRealTime(&target_time); + LogNT::getInstance()->debug("PictureReader", "miniRunAgain = true..."); - target_time.tv_nsec += 1000000LL * 10; + } while(miniRunAgain); - if (target_time.tv_nsec > 999999999) - { - target_time.tv_nsec -= 1000000000L; - target_time.tv_sec += 1; - } - - threadLock(); - threadWaitForSignalTimed(&target_time); - threadUnlock(); - //LogNT::getInstance()->debug(TAG, "TVMedia Sleep end Picture Reader"); + ul.lock(); } } @@ -1024,6 +1036,11 @@ void OsdVector::PictureReader::invalidateLoadIndex(LoadIndex index) pict_lock_incoming.lock(); invalid_loadindex.insert(index); pict_lock_incoming.unlock(); + + // From conversion to std::thread + // The thread used to spin every 10ms, now it only waits on the cond + // This method does not signal the main thread, does it need to now? + // Doesn't look like it, but if it does get the 4 lines below } void OsdVector::PictureReader::informFallback(LoadIndex index, int fallback) @@ -1031,6 +1048,7 @@ void OsdVector::PictureReader::informFallback(LoadIndex index, int fallback) pict_lock_incoming.lock(); inform_fallback[index] = fallback; pict_lock_incoming.unlock(); + // Also here, does this need to signal the thread? } void OsdVector::PictureReader::receivePicture(VDR_ResponsePacket* vresp) @@ -1038,9 +1056,13 @@ void OsdVector::PictureReader::receivePicture(VDR_ResponsePacket* vresp) pict_lock_incoming.lock(); pict_incoming.push(vresp); pict_lock_incoming.unlock(); - threadSignal(); -} + // These 4 lines to signal the thread + threadMutex.lock(); + runLoop = true; + threadCond.notify_one(); + threadMutex.unlock(); +} void OsdVector::PictureReader::addStaticImage(unsigned int id) { @@ -1048,7 +1070,11 @@ void OsdVector::PictureReader::addStaticImage(unsigned int id) pict_incoming_static.push(id); invalid_loadindex.erase(((long long) id) << 32LL); pict_lock_incoming.unlock(); - threadSignal(); + + threadMutex.lock(); + runLoop = true; + threadCond.notify_one(); + threadMutex.unlock(); } #if WIN32 diff --git a/osdvector.h b/osdvector.h index 60e43ef..d93cac9 100644 --- a/osdvector.h +++ b/osdvector.h @@ -27,10 +27,11 @@ #include #include #include +#include +#include #include "defines.h" #include "messagequeue.h" -#include "threadsystem.h" #include "osd.h" #include "colour.h" #include "tvmedia.h" @@ -301,7 +302,7 @@ class OsdVector : public Osd, public MessageReceiver PictureReader* reader; }; - class PictureReader: public Thread_TYPE + class PictureReader { public: ~PictureReader(); @@ -321,6 +322,11 @@ class OsdVector : public Osd, public MessageReceiver protected: void threadMethod(); + std::mutex threadMutex; + std::thread readerThread; + bool threadReqQuit{}; + std::condition_variable threadCond; + bool runLoop{}; std::mutex pict_lock_incoming; //locks std::mutex decoders_lock; diff --git a/vdr.cc b/vdr.cc index 2a077a1..376fe94 100644 --- a/vdr.cc +++ b/vdr.cc @@ -617,7 +617,7 @@ void VDR_PacketReceiver::call(void* userTag, bool& r_deregisterEDR, bool& r_wake // delete the EDR. It's made once per media requested and wasn't owned/deleted by anything before VDR_ResponsePacket* vresp = reinterpret_cast(userTag); - LogNT::getInstance()->debug(TAG, "TVMedia Pictures arrived VDR %x", vresp->getStreamID()); + LogNT::getInstance()->debug(TAG, "TVMedia Pictures arrived VDR {:#x}", vresp->getStreamID()); OsdVector *osd=dynamic_cast(Osd::getInstance()); if (osd) osd->getPictReader()->receivePicture(vresp); // else delete vresp; //nonsense // only rpi does CHANNEL_TVMEDIA, rpi has osdvector. therefore, can't get here. -- 2.39.5