1/* 2 * Copyright (C) 2010 Apple Inc. All rights reserved. 3 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 24 * THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include "config.h" 28#include "RunLoop.h" 29 30#include "WorkItem.h" 31 32#include <QApplication> 33#include <QAbstractEventDispatcher> 34#include <QObject> 35#include <QMetaMethod> 36#include <QMetaObject> 37#include <QTimerEvent> 38 39class RunLoop::TimerObject : public QObject 40{ 41 Q_OBJECT 42public: 43 TimerObject(RunLoop* runLoop) : m_runLoop(runLoop) 44 { 45 int methodIndex = metaObject()->indexOfMethod("performWork()"); 46 m_method = metaObject()->method(methodIndex); 47 } 48 49 Q_SLOT void performWork() { m_runLoop->performWork(); } 50 inline void wakeUp() { m_method.invoke(this, Qt::QueuedConnection); } 51 52protected: 53 virtual void timerEvent(QTimerEvent* event) 54 { 55 RunLoop::TimerBase::timerFired(m_runLoop, event->timerId()); 56 } 57 58private: 59 RunLoop* m_runLoop; 60 QMetaMethod m_method; 61}; 62 63void RunLoop::run() 64{ 65 QCoreApplication::exec(); 66} 67 68void RunLoop::stop() 69{ 70 QCoreApplication::exit(); 71} 72 73RunLoop::RunLoop() 74 : m_timerObject(new TimerObject(this)) 75{ 76} 77 78RunLoop::~RunLoop() 79{ 80 delete m_timerObject; 81} 82 83void RunLoop::wakeUp() 84{ 85 m_timerObject->wakeUp(); 86} 87 88// RunLoop::Timer 89 90void RunLoop::TimerBase::timerFired(RunLoop* runLoop, int ID) 91{ 92 TimerMap::iterator it = runLoop->m_activeTimers.find(ID); 93 ASSERT(it != runLoop->m_activeTimers.end()); 94 TimerBase* timer = it->second; 95 96 if (!timer->m_isRepeating) { 97 // Stop the timer (calling stop would need another hash table lookup). 98 runLoop->m_activeTimers.remove(it); 99 runLoop->m_timerObject->killTimer(timer->m_ID); 100 timer->m_ID = 0; 101 } 102 103 timer->fired(); 104} 105 106RunLoop::TimerBase::TimerBase(RunLoop* runLoop) 107 : m_runLoop(runLoop) 108 , m_ID(0) 109 , m_isRepeating(false) 110{ 111} 112 113RunLoop::TimerBase::~TimerBase() 114{ 115 stop(); 116} 117 118void RunLoop::TimerBase::start(double nextFireInterval, bool repeat) 119{ 120 stop(); 121 int millis = static_cast<int>(nextFireInterval * 1000); 122 m_isRepeating = repeat; 123 m_ID = m_runLoop->m_timerObject->startTimer(millis); 124 ASSERT(m_ID); 125 m_runLoop->m_activeTimers.set(m_ID, this); 126} 127 128void RunLoop::TimerBase::stop() 129{ 130 if (!m_ID) 131 return; 132 TimerMap::iterator it = m_runLoop->m_activeTimers.find(m_ID); 133 if (it == m_runLoop->m_activeTimers.end()) 134 return; 135 136 m_runLoop->m_activeTimers.remove(it); 137 m_runLoop->m_timerObject->killTimer(m_ID); 138 m_ID = 0; 139} 140 141bool RunLoop::TimerBase::isActive() const 142{ 143 return m_ID; 144} 145 146#include "RunLoopQt.moc" 147