#ifndef RunLoop_h
#define RunLoop_h
#include <wtf/Deque.h>
#include <wtf/Forward.h>
#include <wtf/FunctionDispatcher.h>
#include <wtf/HashMap.h>
#include <wtf/RetainPtr.h>
#include <wtf/Threading.h>
#if USE(GLIB)
#include <wtf/glib/GMainLoopSource.h>
#endif
#if PLATFORM(EFL)
#include <Ecore.h>
#include <wtf/efl/UniquePtrEfl.h>
#endif
namespace WTF {
class RunLoop : public FunctionDispatcher {
WTF_MAKE_NONCOPYABLE(RunLoop);
public:
WTF_EXPORT_PRIVATE static void initializeMainRunLoop();
WTF_EXPORT_PRIVATE static RunLoop& current();
WTF_EXPORT_PRIVATE static RunLoop& main();
WTF_EXPORT_PRIVATE static bool isMain();
~RunLoop();
virtual void dispatch(std::function<void()>) override;
WTF_EXPORT_PRIVATE static void run();
WTF_EXPORT_PRIVATE void stop();
WTF_EXPORT_PRIVATE void wakeUp();
#if PLATFORM(COCOA)
WTF_EXPORT_PRIVATE void runForDuration(double duration);
#endif
class TimerBase {
friend class RunLoop;
public:
WTF_EXPORT_PRIVATE explicit TimerBase(RunLoop&);
WTF_EXPORT_PRIVATE virtual ~TimerBase();
void startRepeating(double repeatInterval) { start(repeatInterval, true); }
void startRepeating(std::chrono::milliseconds repeatInterval) { startRepeating(repeatInterval.count() * 0.001); }
void startOneShot(double interval) { start(interval, false); }
WTF_EXPORT_PRIVATE void stop();
WTF_EXPORT_PRIVATE bool isActive() const;
virtual void fired() = 0;
private:
WTF_EXPORT_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(COCOA)
static void timerFired(CFRunLoopTimerRef, void*);
RetainPtr<CFRunLoopTimerRef> m_timer;
#elif PLATFORM(EFL)
static bool timerFired(void* data);
Ecore_Timer* m_timer;
bool m_isRepeating;
#elif USE(GLIB)
GMainLoopSource m_timerSource;
#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;
};
class Holder;
private:
RunLoop();
void performWork();
Mutex m_functionQueueLock;
Deque<std::function<void ()>> m_functionQueue;
#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(COCOA)
static void performWork(void*);
RetainPtr<CFRunLoopRef> m_runLoop;
RetainPtr<CFRunLoopSourceRef> m_runLoopSource;
int m_nestingLevel;
#elif PLATFORM(EFL)
Mutex m_pipeLock;
EflUniquePtr<Ecore_Pipe> m_pipe;
Mutex m_wakeUpEventRequestedLock;
bool m_wakeUpEventRequested;
static void wakeUpEvent(void* data, void*, unsigned);
#elif USE(GLIB)
public:
static gboolean queueWork(RunLoop*);
private:
GRefPtr<GMainContext> m_mainContext;
Vector<GRefPtr<GMainLoop>> m_mainLoops;
#endif
};
}
using WTF::RunLoop;
#endif // RunLoop_h