]> git.vomp.tv Git - vompclient.git/commitdiff
EventDispatcher: Switch to std::mutex/cond
authorChris Tallon <chris@vomp.tv>
Mon, 24 Feb 2020 20:37:45 +0000 (20:37 +0000)
committerChris Tallon <chris@vomp.tv>
Mon, 24 Feb 2020 20:37:45 +0000 (20:37 +0000)
eventdispatcher.cc
eventdispatcher.h
vdr.cc

index fae5b101be35ce9e2dbef2d0be0509739264584f..1c87b364a7786efadb67728e07695a03ca1cdc96 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2007 Chris Tallon
+    Copyright 2007-2020 Chris Tallon
 
     This file is part of VOMP.
 
     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 <https://www.gnu.org/licenses/>.
 */
 
 #include "eventdispatcher.h"
-#include <stdlib.h>
-
-
-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<std::mutex> 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<std::mutex> ul(edMutex, std::defer_lock);
+  edr->cond.wait(ul);
 }
index 407e0b7ebf5a493cca315db9ea9d3e8c5e3228fe..99e9ec75cfc45c85c2831f747e1daad733170fc1 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2007 Chris Tallon
+    Copyright 2007-2020 Chris Tallon
 
     This file is part of VOMP.
 
     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 <https://www.gnu.org/licenses/>.
 */
 
 #ifndef EVENTDISPATCHER_H
 #define EVENTDISPATCHER_H
 
-#include <stdio.h>
 #include <list>
-
-#ifndef WIN32
-#include "threadp.h"
-#else
-#include "threadwin.h"
-#endif
+#include <mutex>
+#include <condition_variable>
 
 #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<EDReceiver*> 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 dc2820dd112a0bd4431656556738b315ec145f3a..0a242e71c49880c801c7a511381ca61b174156ef 100644 (file)
--- 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<VDR_PacketReceiver*>(*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;
 }