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