/*
* Copyright (C) 2010 Apple Inc. All rights reserved.
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
* Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef RunLoop_h
#define RunLoop_h
#include <wtf/HashMap.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/ThreadSpecific.h>
#include <wtf/Threading.h>
#include <wtf/Vector.h>
#if PLATFORM(GTK)
#include <wtf/gobject/GRefPtr.h>
typedef struct _GSource GSource;
typedef struct _GMainLoop GMainLoop;
typedef struct _GMainContext GMainContext;
typedef int gboolean;
#endif
class WorkItem;
namespace CoreIPC {
class BinarySemaphore;
}
class RunLoop {
public:
// Must be called from the main thread.
static void initializeMainRunLoop();
static RunLoop* current();
static RunLoop* main();
void scheduleWork(PassOwnPtr<WorkItem>);
#if PLATFORM(WIN)
// The absoluteTime is in seconds, starting on January 1, 1970. The time is assumed to use the
// same time zone as WTF::currentTime(). Dispatches sent (not posted) messages to the passed-in
// set of HWNDs until the semaphore is signaled or absoluteTime is reached. Returns true if the
// semaphore is signaled, false otherwise.
static bool dispatchSentMessagesUntil(const Vector<HWND>& windows, CoreIPC::BinarySemaphore&, double absoluteTime);
#endif
static void run();
void stop();
class TimerBase {
friend class RunLoop;
public:
TimerBase(RunLoop*);
virtual ~TimerBase();
void startRepeating(double repeatInterval) { start(repeatInterval, true); }
void startOneShot(double interval) { start(interval, false); }
void stop();
bool isActive() const;
virtual void fired() = 0;
private:
void start(double nextFireInterval, bool repeat);
RunLoop* m_runLoop;
#if PLATFORM(WIN)
static void timerFired(RunLoop*, uint64_t ID);
uint64_t m_ID;
bool m_isRepeating;
#elif PLATFORM(MAC)
static void timerFired(CFRunLoopTimerRef, void*);
CFRunLoopTimerRef m_timer;
#elif PLATFORM(QT)
static void timerFired(RunLoop*, int ID);
int m_ID;
bool m_isRepeating;
#elif PLATFORM(GTK)
static gboolean timerFiredCallback(RunLoop::TimerBase*);
static void destroyNotifyCallback(RunLoop::TimerBase*);
gboolean isRepeating() const { return m_isRepeating; }
void clearTimerSource();
GRefPtr<GSource> m_timerSource;
gboolean m_isRepeating;
#endif
};
template <typename TimerFiredClass>
class Timer : public TimerBase {
public:
typedef void (TimerFiredClass::*TimerFiredFunction)();
Timer(RunLoop* runLoop, TimerFiredClass* o, TimerFiredFunction f)
: TimerBase(runLoop)
, m_object(o)
, m_function(f)
{
}
private:
virtual void fired() { (m_object->*m_function)(); }
TimerFiredClass* m_object;
TimerFiredFunction m_function;
};
private:
friend class WTF::ThreadSpecific<RunLoop>;
RunLoop();
~RunLoop();
void performWork();
void wakeUp();
Mutex m_workItemQueueLock;
Vector<WorkItem*> m_workItemQueue;
#if PLATFORM(WIN)
static bool registerRunLoopMessageWindowClass();
static LRESULT CALLBACK RunLoopWndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
HWND m_runLoopMessageWindow;
typedef HashMap<uint64_t, TimerBase*> TimerMap;
TimerMap m_activeTimers;
#elif PLATFORM(MAC)
static void performWork(void*);
CFRunLoopRef m_runLoop;
CFRunLoopSourceRef m_runLoopSource;
#elif PLATFORM(QT)
typedef HashMap<int, TimerBase*> TimerMap;
TimerMap m_activeTimers;
class TimerObject;
TimerObject* m_timerObject;
#elif PLATFORM(GTK)
public:
static gboolean queueWork(RunLoop*);
GMainLoop* mainLoop();
private:
GMainContext* m_runLoopContext;
GMainLoop* m_runLoopMain;
#endif
};
#endif // RunLoop_h