From ba09ff97648a00f5c02503c0b810405503fa2a01 Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Mon, 24 Feb 2020 20:37:45 +0000 Subject: [PATCH] EventDispatcher: Switch to std::mutex/cond --- eventdispatcher.cc | 110 +++++++-------------------------------------- eventdispatcher.h | 37 +++++---------- vdr.cc | 21 ++++----- 3 files changed, 36 insertions(+), 132 deletions(-) diff --git a/eventdispatcher.cc b/eventdispatcher.cc index fae5b10..1c87b36 100644 --- a/eventdispatcher.cc +++ b/eventdispatcher.cc @@ -1,5 +1,5 @@ /* - Copyright 2007 Chris Tallon + Copyright 2007-2020 Chris Tallon This file is part of VOMP. @@ -14,33 +14,21 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + along with VOMP. If not, see . */ #include "eventdispatcher.h" -#include - - -EventDispatcher::EventDispatcher() -{ -#ifndef WIN32 - pthread_mutex_init(&mutex, NULL); -#else - mutex = CreateMutex(NULL, FALSE, NULL); -#endif -} void EventDispatcher::edRegister(EDReceiver* edr) { - edLock(); + edMutex.lock(); receivers.push_back(edr); - edUnlock(); + edMutex.unlock(); } bool EventDispatcher::edFindAndCall(void* userTag) { - edLock(); + edMutex.lock(); EDReceiver* edr = NULL; EDRL::iterator i; @@ -55,17 +43,17 @@ bool EventDispatcher::edFindAndCall(void* userTag) if ((i == receivers.end()) || edr->callinprogress || edr->nomorecalls) { - edUnlock(); + edMutex.unlock(); return false; } edr->callinprogress = true; - edUnlock(); + edMutex.unlock(); bool r_deregisterEDR = false; bool r_wakeThread = false; bool r_deleteEDR = false; edr->call(userTag, r_deregisterEDR, r_wakeThread, r_deleteEDR); - edLock(); + edMutex.lock(); edr->callinprogress = false; @@ -96,11 +84,7 @@ bool EventDispatcher::edFindAndCall(void* userTag) if (r_wakeThread) { - #ifndef WIN32 - pthread_cond_signal(&edr->cond); - #else - SetEvent(edr->cond); - #endif + edr->cond.notify_one(); } if (r_deleteEDR) @@ -108,13 +92,13 @@ bool EventDispatcher::edFindAndCall(void* userTag) delete edr; } - edUnlock(); + edMutex.unlock(); return true; } void EventDispatcher::edUnregister(EDReceiver* edr) { - edLock(); + std::unique_lock ul(edMutex); EDRL::iterator i; for(i = receivers.begin(); i != receivers.end(); i++) @@ -124,31 +108,18 @@ void EventDispatcher::edUnregister(EDReceiver* edr) // Not in the list. Already unregistered? Perhaps vdr::connectionDied already removed this streamclient // FIXME, this should probably be done another way. A call to edUnregister with an object that may or may not be in the list? Not good. - if (i == receivers.end()) - { - edUnlock(); - return; - } + if (i == receivers.end()) return; if (!edr->callinprogress) { receivers.erase(i); - edUnlock(); return; } edr->nomorecalls = true; // edUnlock, wait for callinprogres=false (cond to be signalled), lock -#ifndef WIN32 - pthread_cond_wait(&edr->cond, &mutex); -#else - ReleaseMutex(mutex); - WaitForSingleObject(edr->cond,INFINITE); - WaitForSingleObject(mutex, INFINITE); - ResetEvent(edr->cond); - -#endif + edr->cond.wait(ul); for(i = receivers.begin(); i != receivers.end(); i++) { @@ -158,27 +129,6 @@ void EventDispatcher::edUnregister(EDReceiver* edr) if (i == receivers.end()) abort(); // should never happen receivers.erase(i); - edUnlock(); -} - -// --------------------------------------- - -void EventDispatcher::edLock() -{ -#ifndef WIN32 - pthread_mutex_lock(&mutex); -#else - WaitForSingleObject(mutex, INFINITE); -#endif -} - -void EventDispatcher::edUnlock() -{ -#ifndef WIN32 - pthread_mutex_unlock(&mutex); -#else - ReleaseMutex(mutex); -#endif } // --------------------------------------- @@ -186,36 +136,6 @@ void EventDispatcher::edUnlock() void EventDispatcher::edSleepThisReceiver(EDReceiver* edr) { // For blocking version, not callback version. Call with edLock locked - -#ifndef WIN32 - pthread_cond_wait(&edr->cond, &mutex); -#else - ResetEvent(edr->cond); - ReleaseMutex(mutex); - WaitForSingleObject(edr->cond,INFINITE); - ResetEvent(edr->cond); - WaitForSingleObject(mutex, INFINITE); -#endif -} - -// -------------- EDReceiver implementation - -EDReceiver::EDReceiver() -{ - nomorecalls = false; - callinprogress = false; -#ifndef WIN32 - pthread_cond_init(&cond, NULL); -#else - cond = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL); -#endif -} - -EDReceiver::~EDReceiver() -{ -#ifdef WIN32 - if (cond!=NULL) CloseHandle(cond); -#else - pthread_cond_destroy(&cond); -#endif + std::unique_lock ul(edMutex, std::defer_lock); + edr->cond.wait(ul); } diff --git a/eventdispatcher.h b/eventdispatcher.h index 407e0b7..99e9ec7 100644 --- a/eventdispatcher.h +++ b/eventdispatcher.h @@ -1,5 +1,5 @@ /* - Copyright 2007 Chris Tallon + Copyright 2007-2020 Chris Tallon This file is part of VOMP. @@ -14,31 +14,24 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + along with VOMP. If not, see . */ #ifndef EVENTDISPATCHER_H #define EVENTDISPATCHER_H -#include #include - -#ifndef WIN32 -#include "threadp.h" -#else -#include "threadwin.h" -#endif +#include +#include #include "defines.h" -class EDReceiver //(implementation in eventdispatcher.cc) +class EDReceiver { friend class EventDispatcher; public: - EDReceiver(); - virtual ~EDReceiver(); + virtual ~EDReceiver() {}; protected: virtual void call(void* userTag, bool& r_deregisterEDR, bool& r_wakeThread, bool& deleteEDR)=0; // Implementor must override this and do the actual call @@ -46,23 +39,17 @@ class EDReceiver //(implementation in eventdispatcher.cc) // r_deregisterEDR: true = remove EDReceiver from list after call // r_wakeThread: true = wake up a RequestResponse thread which is waiting for a VDR response // r_deleteEDR: true = delete the EDReceiver object once the call has finished - bool nomorecalls; - bool callinprogress; + bool nomorecalls{}; + bool callinprogress{}; -#ifndef WIN32 - pthread_cond_t cond; -#else - HANDLE cond; -#endif + std::condition_variable cond; }; class EventDispatcher { - public: typedef std::list EDRL; - EventDispatcher(); virtual ~EventDispatcher() {}; protected: @@ -80,11 +67,7 @@ class EventDispatcher EDRL receivers; -#ifndef WIN32 - pthread_mutex_t mutex; -#else - HANDLE mutex; -#endif + std::mutex edMutex; }; #endif diff --git a/vdr.cc b/vdr.cc index dc2820d..0a242e7 100644 --- a/vdr.cc +++ b/vdr.cc @@ -488,7 +488,7 @@ void VDR::connectionDied() // If it's a stream receiver, generate a stream packet with flag == connection_lost - edLock(); + edMutex.lock(); VDR_PacketReceiver* vdrpr; VDR_ResponsePacket* vresp; while(receivers.size()) @@ -499,7 +499,7 @@ void VDR::connectionDied() vresp = new VDR_ResponsePacket(); vresp->setResponse(vdrpr->requestSerialNumber, NULL, 0); logger->log("VDR", Log::DEBUG, "Timeouts: created blank response packet for request serial %lu", vdrpr->requestSerialNumber); - edUnlock(); + edMutex.unlock(); if (!edFindAndCall(vresp)) // makes ED lock, find receiver for vresp (using ed_cb_find() ) and then call (using ed_cb_call() ) { // If edFindAndCall returns true, edr was called and vresp was handed off. @@ -507,14 +507,14 @@ void VDR::connectionDied() logger->log("VDR", Log::ERR, "Timeouts: no waiting thread found for request serial %lu !!!", vdrpr->requestSerialNumber); delete vresp; } - edLock(); + edMutex.lock(); } else if (vdrpr->receiverChannel == CHANNEL_STREAM || vdrpr->receiverChannel == CHANNEL_TVMEDIA) { vresp = new VDR_ResponsePacket(); vresp->setStream(vdrpr->streamID, 2 /* connection-lost flag */ , NULL, 0, vdrpr->receiverChannel); logger->log("VDR", Log::DEBUG, "Timeouts: created blank response packet for streamid %lu", vdrpr->streamID); - edUnlock(); + edMutex.unlock(); if (!edFindAndCall(vresp)) // makes ED lock, find receiver for vresp (using ed_cb_find() ) and then call (using ed_cb_call() ) { // If edFindAndCall returns true, edr was called and vresp was handed off. @@ -522,13 +522,13 @@ void VDR::connectionDied() logger->log("VDR", Log::ERR, "Timeouts: no waiting stream receiver found for streamid %lu !!!", vdrpr->streamID); delete vresp; } - edLock(); - + edMutex.lock(); + for(EDRL::iterator i = receivers.begin(); i != receivers.end(); i++) if (dynamic_cast(*i) == vdrpr) { receivers.erase(i); break; } } } - edUnlock(); + edMutex.unlock(); // Ok, all event receviers should be dealt with. just in case there weren't any, inform command logger->log("VDR", Log::DEBUG, "edUnlock at end of connectionDied"); @@ -587,11 +587,12 @@ VDR_ResponsePacket* VDR::RequestResponse(VDR_RequestPacket* vrp) edRegister(&vdrpr); - edLock(); + edMutex.lock(); + if ((ULONG)tcp->sendData(vrp->getPtr(), vrp->getLen()) != vrp->getLen()) { - edUnlock(); + edMutex.unlock(); edUnregister(&vdrpr); VDR_ResponsePacket* vresp = new VDR_ResponsePacket(); return vresp; // "no-response" return @@ -605,7 +606,7 @@ VDR_ResponsePacket* VDR::RequestResponse(VDR_RequestPacket* vrp) // Woken because a response packet has arrived, mutex will be locked // logger->log("VDR", Log::DEBUG, "Packet delivered to me, requestID: %lu", vdrpr.save_vresp->getRequestID()); - edUnlock(); + edMutex.unlock(); return vdrpr.save_vresp; } -- 2.39.2