Skip to content

Instantly share code, notes, and snippets.

@annulen
Last active April 22, 2016 17:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save annulen/9e3ef3ea2987957dc1bc882e58ee0c9d to your computer and use it in GitHub Desktop.
Save annulen/9e3ef3ea2987957dc1bc882e58ee0c9d to your computer and use it in GitHub Desktop.
diff --git a/Source/WTF/wtf/qt/RunLoopQt.cpp b/Source/WTF/wtf/qt/RunLoopQt.cpp
index c728d0f..c13b1a2 100644
--- a/Source/WTF/wtf/qt/RunLoopQt.cpp
+++ b/Source/WTF/wtf/qt/RunLoopQt.cpp
@@ -32,6 +32,7 @@
#include <QMetaMethod>
#include <QMetaObject>
#include <QObject>
+#include <QThread>
#include <QTimerEvent>
namespace WTF {
@@ -39,24 +40,60 @@ namespace WTF {
class RunLoop::TimerObject : public QObject {
Q_OBJECT
public:
- TimerObject(RunLoop* runLoop)
+ TimerObject(RunLoop& runLoop)
: m_runLoop(runLoop)
{
int methodIndex = metaObject()->indexOfMethod("performWork()");
m_method = metaObject()->method(methodIndex);
+
+ bool result;
+ result = connect(this, &TimerObject::requestStart,
+ this, &TimerObject::start, Qt::BlockingQueuedConnection);
+ ASSERT_UNUSED(result, result);
+ result = connect(this, &TimerObject::requestStop,
+ this, &TimerObject::stop, Qt::BlockingQueuedConnection);
+ ASSERT_UNUSED(result, result);
}
- Q_SLOT void performWork() { m_runLoop->performWork(); }
+ Q_SLOT void performWork() { m_runLoop.performWork(); }
inline void wakeUp() { m_method.invoke(this, Qt::QueuedConnection); }
+ inline bool isInCurrentThread() { return thread() == QThread::currentThread(); }
+
+ Q_SIGNAL void requestStart(double nextFireInterval, RunLoop::TimerBase* timer);
+ Q_SLOT void start(double nextFireInterval, RunLoop::TimerBase* timer)
+ {
+ ASSERT(isInCurrentThread());
+ if (timer->m_ID)
+ stop(timer->m_ID);
+
+ int millis = static_cast<int>(nextFireInterval * 1000);
+ timer->m_ID = startTimer(millis);
+ ASSERT(timer->m_ID);
+ m_runLoop.m_activeTimers.set(timer->m_ID, timer);
+ }
+
+ Q_SIGNAL void requestStop(int timerID);
+ Q_SLOT void stop(int timerID)
+ {
+ ASSERT(isInCurrentThread());
+ ASSERT(timerID);
+ TimerMap::iterator it = m_runLoop.m_activeTimers.find(timerID);
+ if (it == m_runLoop.m_activeTimers.end())
+ return;
+
+ m_runLoop.m_activeTimers.remove(it);
+ m_runLoop.m_timerObject->killTimer(timerID);
+ }
+
protected:
void timerEvent(QTimerEvent* event) override
{
- RunLoop::TimerBase::timerFired(m_runLoop, event->timerId());
+ RunLoop::TimerBase::timerFired(&m_runLoop, event->timerId());
}
private:
- RunLoop* m_runLoop;
+ RunLoop& m_runLoop;
QMetaMethod m_method;
};
@@ -90,7 +127,7 @@ void RunLoop::stop()
}
RunLoop::RunLoop()
- : m_timerObject(new TimerObject(this))
+ : m_timerObject(new TimerObject(*this))
{
}
@@ -136,24 +173,24 @@ RunLoop::TimerBase::~TimerBase()
void RunLoop::TimerBase::start(double nextFireInterval, bool repeat)
{
- stop();
- int millis = static_cast<int>(nextFireInterval * 1000);
+ if (LIKELY(m_runLoop.m_timerObject->isInCurrentThread()))
+ m_runLoop.m_timerObject->start(nextFireInterval, this);
+ else
+ m_runLoop.m_timerObject->requestStart(nextFireInterval, this);
+
m_isRepeating = repeat;
- m_ID = m_runLoop.m_timerObject->startTimer(millis);
- ASSERT(m_ID);
- m_runLoop.m_activeTimers.set(m_ID, this);
}
void RunLoop::TimerBase::stop()
{
if (!m_ID)
return;
- TimerMap::iterator it = m_runLoop.m_activeTimers.find(m_ID);
- if (it == m_runLoop.m_activeTimers.end())
- return;
- m_runLoop.m_activeTimers.remove(it);
- m_runLoop.m_timerObject->killTimer(m_ID);
+ if (LIKELY(m_runLoop.m_timerObject->isInCurrentThread()))
+ m_runLoop.m_timerObject->stop(m_ID);
+ else
+ m_runLoop.m_timerObject->requestStop(m_ID);
+
m_ID = 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment