/*
- 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;
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;
if (r_wakeThread)
{
- #ifndef WIN32
- pthread_cond_signal(&edr->cond);
- #else
- SetEvent(edr->cond);
- #endif
+ edr->cond.notify_one();
}
if (r_deleteEDR)
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++)
// 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++)
{
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
}
// ---------------------------------------
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);
}
/*
- 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
// 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:
EDRL receivers;
-#ifndef WIN32
- pthread_mutex_t mutex;
-#else
- HANDLE mutex;
-#endif
+ std::mutex edMutex;
};
#endif
// 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())
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.
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.
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");
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
// 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;
}