fixed: events were added before event queue was ready, caused debug build assert failure.
removed sleep hack in favour of cond var wait.
This commit is contained in:
parent
0d087d4edc
commit
45c1cde698
|
@ -18,12 +18,15 @@
|
|||
|
||||
#include "base/EventQueue.h"
|
||||
|
||||
#include "mt/Mutex.h"
|
||||
#include "mt/Lock.h"
|
||||
#include "arch/Arch.h"
|
||||
#include "base/Log.h"
|
||||
#include "base/SimpleEventQueueBuffer.h"
|
||||
#include "base/Stopwatch.h"
|
||||
#include "base/IEventJob.h"
|
||||
#include "base/EventTypes.h"
|
||||
#include "base/Log.h"
|
||||
#include "base/XBase.h"
|
||||
|
||||
EVENT_TYPE_ACCESSOR(CClient)
|
||||
EVENT_TYPE_ACCESSOR(IStream)
|
||||
|
@ -78,7 +81,9 @@ CEventQueue::CEventQueue() :
|
|||
m_typesForCServerApp(NULL),
|
||||
m_typesForIKeyState(NULL),
|
||||
m_typesForIPrimaryScreen(NULL),
|
||||
m_typesForIScreen(NULL)
|
||||
m_typesForIScreen(NULL),
|
||||
m_readyMutex(new CMutex),
|
||||
m_readyCondVar(new CCondVar<bool>(m_readyMutex, false))
|
||||
{
|
||||
m_mutex = ARCH->newMutex();
|
||||
ARCH->setSignalHandler(CArch::kINTERRUPT, &interrupt, this);
|
||||
|
@ -89,6 +94,9 @@ CEventQueue::CEventQueue() :
|
|||
CEventQueue::~CEventQueue()
|
||||
{
|
||||
delete m_buffer;
|
||||
delete m_readyCondVar;
|
||||
delete m_readyMutex;
|
||||
|
||||
ARCH->setSignalHandler(CArch::kINTERRUPT, NULL, NULL);
|
||||
ARCH->setSignalHandler(CArch::kTERMINATE, NULL, NULL);
|
||||
ARCH->closeMutex(m_mutex);
|
||||
|
@ -98,6 +106,16 @@ void
|
|||
CEventQueue::loop()
|
||||
{
|
||||
m_buffer->init();
|
||||
*m_readyCondVar = true;
|
||||
m_readyCondVar->broadcast();
|
||||
|
||||
LOG((CLOG_DEBUG "event queue is ready"));
|
||||
while (!m_pending.empty()) {
|
||||
LOG((CLOG_DEBUG "add pending events to buffer"));
|
||||
CEvent& event = m_pending.front();
|
||||
addEventToBuffer(event);
|
||||
m_pending.pop();
|
||||
}
|
||||
|
||||
CEvent event;
|
||||
getEvent(event);
|
||||
|
@ -268,18 +286,27 @@ CEventQueue::addEvent(const CEvent& event)
|
|||
dispatchEvent(event);
|
||||
CEvent::deleteData(event);
|
||||
}
|
||||
else if (!(*m_readyCondVar)) {
|
||||
m_pending.push(event);
|
||||
}
|
||||
else {
|
||||
CArchMutexLock lock(m_mutex);
|
||||
|
||||
// store the event's data locally
|
||||
UInt32 eventID = saveEvent(event);
|
||||
|
||||
// add it
|
||||
if (!m_buffer->addEvent(eventID)) {
|
||||
// failed to send event
|
||||
removeEvent(eventID);
|
||||
CEvent::deleteData(event);
|
||||
}
|
||||
addEventToBuffer(event);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CEventQueue::addEventToBuffer(const CEvent& event)
|
||||
{
|
||||
CArchMutexLock lock(m_mutex);
|
||||
|
||||
// store the event's data locally
|
||||
UInt32 eventID = saveEvent(event);
|
||||
|
||||
// add it
|
||||
if (!m_buffer->addEvent(eventID)) {
|
||||
// failed to send event
|
||||
removeEvent(eventID);
|
||||
CEvent::deleteData(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -526,6 +553,21 @@ CEventQueue::getSystemTarget()
|
|||
return &m_systemTarget;
|
||||
}
|
||||
|
||||
void
|
||||
CEventQueue::waitForReady() const
|
||||
{
|
||||
double timeout = ARCH->time() + 5;
|
||||
m_readyCondVar->lock();
|
||||
|
||||
while (!m_readyCondVar->wait()) {
|
||||
if(ARCH->time() > timeout) {
|
||||
throw std::runtime_error("event queue is not ready within 5 sec");
|
||||
}
|
||||
}
|
||||
|
||||
m_readyCondVar->unlock();
|
||||
}
|
||||
|
||||
//
|
||||
// CEventQueue::CTimer
|
||||
//
|
||||
|
|
|
@ -18,14 +18,19 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "mt/CondVar.h"
|
||||
#include "arch/IArchMultithread.h"
|
||||
#include "base/IEventQueue.h"
|
||||
#include "base/Event.h"
|
||||
#include "base/PriorityQueue.h"
|
||||
#include "base/Stopwatch.h"
|
||||
#include "arch/IArchMultithread.h"
|
||||
#include "common/stdmap.h"
|
||||
#include "common/stdset.h"
|
||||
|
||||
#include <queue>
|
||||
|
||||
class CMutex;
|
||||
|
||||
//! Event queue
|
||||
/*!
|
||||
An event queue that implements the platform independent parts and
|
||||
|
@ -59,13 +64,15 @@ public:
|
|||
virtual CEvent::Type
|
||||
getRegisteredType(const CString& name) const;
|
||||
void* getSystemTarget();
|
||||
virtual void waitForReady() const;
|
||||
|
||||
private:
|
||||
UInt32 saveEvent(const CEvent& event);
|
||||
CEvent removeEvent(UInt32 eventID);
|
||||
bool hasTimerExpired(CEvent& event);
|
||||
double getNextTimerTimeout() const;
|
||||
|
||||
void addEventToBuffer(const CEvent& event);
|
||||
|
||||
private:
|
||||
class CTimer {
|
||||
public:
|
||||
|
@ -170,6 +177,9 @@ private:
|
|||
IKeyStateEvents* m_typesForIKeyState;
|
||||
IPrimaryScreenEvents* m_typesForIPrimaryScreen;
|
||||
IScreenEvents* m_typesForIScreen;
|
||||
CMutex* m_readyMutex;
|
||||
CCondVar<bool>* m_readyCondVar;
|
||||
std::queue<const CEvent> m_pending;
|
||||
};
|
||||
|
||||
#define EVENT_TYPE_ACCESSOR(type_) \
|
||||
|
|
|
@ -176,6 +176,13 @@ public:
|
|||
registerTypeOnce(CEvent::Type& type,
|
||||
const char* name) = 0;
|
||||
|
||||
//! Wait for event queue to become ready
|
||||
/*!
|
||||
Blocks on the current thread until the event queue is ready for events to
|
||||
be added.
|
||||
*/
|
||||
virtual void waitForReady() const = 0;
|
||||
|
||||
//@}
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
|
|
@ -28,9 +28,6 @@ COSXDragView* g_dragView = NULL;
|
|||
void
|
||||
runCocoaApp()
|
||||
{
|
||||
// HACK: sleep, carbon loop should start first.
|
||||
usleep(1000000);
|
||||
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
[NSApplication sharedApplication];
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "platform/OSXScreen.h"
|
||||
|
||||
#include "base/EventQueue.h"
|
||||
#include "client/Client.h"
|
||||
#include "platform/OSXClipboard.h"
|
||||
#include "platform/OSXEventQueueBuffer.h"
|
||||
|
@ -163,6 +164,10 @@ COSXScreen::COSXScreen(IEventQueue* events, bool isPrimary, bool autoShowHideCur
|
|||
|
||||
// create thread for monitoring system power state.
|
||||
*m_pmThreadReady = false;
|
||||
#if defined(MAC_OS_X_VERSION_10_7)
|
||||
m_carbonLoopMutex = new CMutex();
|
||||
m_carbonLoopReady = new CCondVar<bool>(m_carbonLoopMutex, false);
|
||||
#endif
|
||||
LOG((CLOG_DEBUG "starting watchSystemPowerThread"));
|
||||
m_pmWatchThread = new CThread(new TMethodJob<COSXScreen>
|
||||
(this, &COSXScreen::watchSystemPowerThread));
|
||||
|
@ -255,6 +260,11 @@ COSXScreen::~COSXScreen()
|
|||
|
||||
delete m_keyState;
|
||||
delete m_screensaver;
|
||||
|
||||
#if defined(MAC_OS_X_VERSION_10_7)
|
||||
delete m_carbonLoopMutex;
|
||||
delete m_carbonLoopReady;
|
||||
#endif
|
||||
}
|
||||
|
||||
void*
|
||||
|
@ -1694,10 +1704,16 @@ COSXScreen::watchSystemPowerThread(void*)
|
|||
}
|
||||
|
||||
LOG((CLOG_DEBUG "started watchSystemPowerThread"));
|
||||
|
||||
m_events->waitForReady();
|
||||
|
||||
// HACK: sleep, this seem to stop synergy from freezing.
|
||||
ARCH->sleep(1);
|
||||
|
||||
#if defined(MAC_OS_X_VERSION_10_7)
|
||||
if (*m_carbonLoopReady == false) {
|
||||
*m_carbonLoopReady = true;
|
||||
m_carbonLoopReady->broadcast();
|
||||
}
|
||||
#endif
|
||||
|
||||
// start the run loop
|
||||
LOG((CLOG_DEBUG "starting carbon loop"));
|
||||
CFRunLoopRun();
|
||||
|
@ -2100,6 +2116,21 @@ COSXScreen::getDraggingFilename()
|
|||
return m_draggingFilename;
|
||||
}
|
||||
|
||||
void
|
||||
COSXScreen::waitForCarbonLoop() const
|
||||
{
|
||||
double timeout = ARCH->time() + 5;
|
||||
m_carbonLoopReady->lock();
|
||||
|
||||
while (!m_carbonLoopReady->wait()) {
|
||||
if(ARCH->time() > timeout) {
|
||||
throw std::runtime_error("carbon loop is not ready within 5 sec");
|
||||
}
|
||||
}
|
||||
|
||||
m_carbonLoopReady->unlock();
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
void
|
||||
|
|
|
@ -47,6 +47,7 @@ class CThread;
|
|||
class COSXKeyState;
|
||||
class COSXScreenSaver;
|
||||
class IEventQueue;
|
||||
class CMutex;
|
||||
|
||||
//! Implementation of IPlatformScreen for OS X
|
||||
class COSXScreen : public CPlatformScreen {
|
||||
|
@ -98,6 +99,7 @@ public:
|
|||
virtual CString& getDraggingFilename();
|
||||
|
||||
const CString& getDropTarget() const { return m_dropTarget; }
|
||||
void waitForCarbonLoop() const;
|
||||
|
||||
protected:
|
||||
// IPlatformScreen overrides
|
||||
|
@ -344,4 +346,9 @@ private:
|
|||
|
||||
CThread* m_getDropTargetThread;
|
||||
CString m_dropTarget;
|
||||
|
||||
#if defined(MAC_OS_X_VERSION_10_7)
|
||||
CMutex* m_carbonLoopMutex;
|
||||
CCondVar<bool>* m_carbonLoopReady;
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -548,8 +548,10 @@ CClientApp::mainLoop()
|
|||
this, &CClientApp::runEventsLoop,
|
||||
NULL));
|
||||
|
||||
// HACK: sleep, allow queue to start.
|
||||
ARCH->sleep(1);
|
||||
// wait until carbon loop is ready
|
||||
COSXScreen* screen = dynamic_cast<COSXScreen*>(
|
||||
s_clientScreen->getPlatformScreen());
|
||||
screen->waitForCarbonLoop();
|
||||
|
||||
runCocoaApp();
|
||||
#else
|
||||
|
|
|
@ -296,6 +296,8 @@ public:
|
|||
virtual void getShape(SInt32& x, SInt32& y,
|
||||
SInt32& width, SInt32& height) const;
|
||||
virtual void getCursorPos(SInt32& x, SInt32& y) const;
|
||||
|
||||
IPlatformScreen* getPlatformScreen() { return m_screen; }
|
||||
|
||||
protected:
|
||||
void enablePrimary();
|
||||
|
|
|
@ -798,8 +798,10 @@ CServerApp::mainLoop()
|
|||
this, &CServerApp::runEventsLoop,
|
||||
NULL));
|
||||
|
||||
// HACK: sleep, allow queue to start.
|
||||
ARCH->sleep(1);
|
||||
// wait until carbon loop is ready
|
||||
COSXScreen* screen = dynamic_cast<COSXScreen*>(
|
||||
s_serverScreen->getPlatformScreen());
|
||||
screen->waitForCarbonLoop();
|
||||
|
||||
runCocoaApp();
|
||||
#else
|
||||
|
|
|
@ -61,4 +61,5 @@ public:
|
|||
MOCK_METHOD0(forIKeyState, IKeyStateEvents&());
|
||||
MOCK_METHOD0(forIPrimaryScreen, IPrimaryScreenEvents&());
|
||||
MOCK_METHOD0(forIScreen, IScreenEvents&());
|
||||
MOCK_CONST_METHOD0(waitForReady, void());
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue