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 39 class RunLoop::TimerObject : public QObject 40 { 41 Q_OBJECT 42 public: 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 52 protected: 53 virtual void timerEvent(QTimerEvent* event) 54 { 55 RunLoop::TimerBase::timerFired(m_runLoop, event->timerId()); 56 } 57 58 private: 59 RunLoop* m_runLoop; 60 QMetaMethod m_method; 61 }; 62 63 void RunLoop::run() 64 { 65 QCoreApplication::exec(); 66 } 67 68 void RunLoop::stop() 69 { 70 QCoreApplication::exit(); 71 } 72 73 RunLoop::RunLoop() 74 : m_timerObject(new TimerObject(this)) 75 { 76 } 77 78 RunLoop::~RunLoop() 79 { 80 delete m_timerObject; 81 } 82 83 void RunLoop::wakeUp() 84 { 85 m_timerObject->wakeUp(); 86 } 87 88 // RunLoop::Timer 89 90 void 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 106 RunLoop::TimerBase::TimerBase(RunLoop* runLoop) 107 : m_runLoop(runLoop) 108 , m_ID(0) 109 , m_isRepeating(false) 110 { 111 } 112 113 RunLoop::TimerBase::~TimerBase() 114 { 115 stop(); 116 } 117 118 void 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 128 void 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 141 bool RunLoop::TimerBase::isActive() const 142 { 143 return m_ID; 144 } 145 146 #include "RunLoopQt.moc" 147