chore: Switched event buffer from Carbon to GCD
This commit is contained in:
parent
415fc3ea63
commit
30a37a8a50
2 changed files with 56 additions and 64 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
* SPDX-FileCopyrightText: (C) 2025 Stephen Jensen <sjensen313@proton.me>
|
||||||
|
* SPDX-FileCopyrightText: (C) 2012 - 2025 Symless Ltd.
|
||||||
* SPDX-FileCopyrightText: (C) 2004 Chris Schoeneman
|
* SPDX-FileCopyrightText: (C) 2004 Chris Schoeneman
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
*/
|
*/
|
||||||
|
|
@ -9,6 +10,7 @@
|
||||||
|
|
||||||
#include "base/Event.h"
|
#include "base/Event.h"
|
||||||
#include "base/IEventQueue.h"
|
#include "base/IEventQueue.h"
|
||||||
|
#include "base/Log.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// EventQueueTimer
|
// EventQueueTimer
|
||||||
|
|
@ -22,86 +24,70 @@ class EventQueueTimer
|
||||||
// OSXEventQueueBuffer
|
// OSXEventQueueBuffer
|
||||||
//
|
//
|
||||||
|
|
||||||
OSXEventQueueBuffer::OSXEventQueueBuffer(IEventQueue *events)
|
OSXEventQueueBuffer::OSXEventQueueBuffer(IEventQueue *events) : m_eventQueue(events)
|
||||||
: m_event(NULL),
|
|
||||||
m_eventQueue(events),
|
|
||||||
m_carbonEventQueue(NULL)
|
|
||||||
{
|
{
|
||||||
// do nothing
|
// Initialization is now managed using modern constructs
|
||||||
}
|
}
|
||||||
|
|
||||||
OSXEventQueueBuffer::~OSXEventQueueBuffer()
|
OSXEventQueueBuffer::~OSXEventQueueBuffer()
|
||||||
{
|
{
|
||||||
// release the last event
|
// No explicit clean-up needed as GCD and STL handle resource management
|
||||||
if (m_event != NULL) {
|
|
||||||
ReleaseEvent(m_event);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSXEventQueueBuffer::init()
|
void OSXEventQueueBuffer::init()
|
||||||
{
|
{
|
||||||
m_carbonEventQueue = GetCurrentEventQueue();
|
// No initialization needed for GCD-based implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSXEventQueueBuffer::waitForEvent(double timeout)
|
void OSXEventQueueBuffer::waitForEvent(double timeout)
|
||||||
{
|
{
|
||||||
EventRef event;
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
ReceiveNextEvent(0, NULL, timeout, false, &event);
|
if (m_dataQueue.empty()) {
|
||||||
|
auto duration = std::chrono::duration<double>(timeout);
|
||||||
|
LOG_DEBUG2("waiting for event, timeout: %f seconds", timeout);
|
||||||
|
m_cond.wait_for(lock, duration, [this] { return !m_dataQueue.empty(); });
|
||||||
|
} else {
|
||||||
|
LOG_DEBUG2("found events in the queue");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEventQueueBuffer::Type OSXEventQueueBuffer::getEvent(Event &event, uint32_t &dataID)
|
IEventQueueBuffer::Type OSXEventQueueBuffer::getEvent(Event &event, uint32_t &dataID)
|
||||||
{
|
{
|
||||||
// release the previous event
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
if (m_event != NULL) {
|
if (m_dataQueue.empty()) {
|
||||||
ReleaseEvent(m_event);
|
LOG_DEBUG2("no events in queue");
|
||||||
m_event = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the next event
|
|
||||||
OSStatus error = ReceiveNextEvent(0, NULL, 0.0, true, &m_event);
|
|
||||||
|
|
||||||
// handle the event
|
|
||||||
if (error == eventLoopQuitErr) {
|
|
||||||
event = Event(Event::kQuit);
|
|
||||||
return kSystem;
|
|
||||||
} else if (error != noErr) {
|
|
||||||
return kNone;
|
return kNone;
|
||||||
} else {
|
|
||||||
uint32_t eventClass = GetEventClass(m_event);
|
|
||||||
switch (eventClass) {
|
|
||||||
case 'Syne':
|
|
||||||
dataID = GetEventKind(m_event);
|
|
||||||
return kUser;
|
|
||||||
|
|
||||||
default:
|
|
||||||
event = Event(Event::kSystem, m_eventQueue->getSystemTarget(), &m_event);
|
|
||||||
return kSystem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dataID = m_dataQueue.front();
|
||||||
|
m_dataQueue.pop();
|
||||||
|
lock.unlock(); // Unlock early to allow other threads to proceed
|
||||||
|
|
||||||
|
LOG_DEBUG2("handled user event with dataID: %u", dataID);
|
||||||
|
return kUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OSXEventQueueBuffer::addEvent(uint32_t dataID)
|
bool OSXEventQueueBuffer::addEvent(uint32_t dataID)
|
||||||
{
|
{
|
||||||
EventRef event;
|
// Use GCD to dispatch event addition on the main queue
|
||||||
OSStatus error = CreateEvent(kCFAllocatorDefault, 'Syne', dataID, 0, kEventAttributeNone, &event);
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
std::lock_guard<std::mutex> lock(this->m_mutex);
|
||||||
|
LOG_DEBUG2("adding user event with dataID: %u", dataID);
|
||||||
|
this->m_dataQueue.push(dataID);
|
||||||
|
this->m_cond.notify_one();
|
||||||
|
LOG_DEBUG2("user event added to queue, dataID=%u", dataID);
|
||||||
|
});
|
||||||
|
|
||||||
if (error == noErr) {
|
// Always return true since dispatch_async does not fail under normal conditions
|
||||||
|
return true;
|
||||||
assert(m_carbonEventQueue != NULL);
|
|
||||||
|
|
||||||
error = PostEventToQueue(m_carbonEventQueue, event, kEventPriorityStandard);
|
|
||||||
|
|
||||||
ReleaseEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (error == noErr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OSXEventQueueBuffer::isEmpty() const
|
bool OSXEventQueueBuffer::isEmpty() const
|
||||||
{
|
{
|
||||||
EventRef event;
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
OSStatus status = ReceiveNextEvent(0, NULL, 0.0, false, &event);
|
bool empty = m_dataQueue.empty();
|
||||||
return (status == eventLoopTimedOutErr);
|
LOG_DEBUG2("queue is %s", empty ? "empty" : "not empty");
|
||||||
|
return empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
EventQueueTimer *OSXEventQueueBuffer::newTimer(double, bool) const
|
EventQueueTimer *OSXEventQueueBuffer::newTimer(double, bool) const
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
* SPDX-FileCopyrightText: (C) 2025 Stephen Jensen <sjensen313@proton.me>
|
||||||
|
* SPDX-FileCopyrightText: (C) 2012 - 2025 Symless Ltd.
|
||||||
* SPDX-FileCopyrightText: (C) 2004 Chris Schoeneman
|
* SPDX-FileCopyrightText: (C) 2004 Chris Schoeneman
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
*/
|
*/
|
||||||
|
|
@ -9,7 +10,10 @@
|
||||||
|
|
||||||
#include "base/IEventQueueBuffer.h"
|
#include "base/IEventQueueBuffer.h"
|
||||||
|
|
||||||
#include <Carbon/Carbon.h>
|
#include <condition_variable>
|
||||||
|
#include <dispatch/dispatch.h>
|
||||||
|
#include <mutex>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
class IEventQueue;
|
class IEventQueue;
|
||||||
|
|
||||||
|
|
@ -21,16 +25,18 @@ public:
|
||||||
virtual ~OSXEventQueueBuffer();
|
virtual ~OSXEventQueueBuffer();
|
||||||
|
|
||||||
// IEventQueueBuffer overrides
|
// IEventQueueBuffer overrides
|
||||||
virtual void init();
|
virtual void init() override;
|
||||||
virtual void waitForEvent(double timeout);
|
virtual void waitForEvent(double timeout) override;
|
||||||
virtual Type getEvent(Event &event, uint32_t &dataID);
|
virtual Type getEvent(Event &event, uint32_t &dataID) override;
|
||||||
virtual bool addEvent(uint32_t dataID);
|
virtual bool addEvent(uint32_t dataID) override;
|
||||||
virtual bool isEmpty() const;
|
virtual bool isEmpty() const override;
|
||||||
virtual EventQueueTimer *newTimer(double duration, bool oneShot) const;
|
virtual EventQueueTimer *newTimer(double duration, bool oneShot) const override;
|
||||||
virtual void deleteTimer(EventQueueTimer *) const;
|
virtual void deleteTimer(EventQueueTimer *timer) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EventRef m_event;
|
|
||||||
IEventQueue *m_eventQueue;
|
IEventQueue *m_eventQueue;
|
||||||
EventQueueRef m_carbonEventQueue;
|
|
||||||
|
mutable std::mutex m_mutex;
|
||||||
|
std::condition_variable m_cond;
|
||||||
|
std::queue<uint32_t> m_dataQueue;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue