1/*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
4 * Portions Copyright (c) 2010 Motorola Mobility, Inc.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25 * THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#ifndef RunLoop_h
29#define RunLoop_h
30
31#include <wtf/Deque.h>
32#include <wtf/Forward.h>
33#include <wtf/FunctionDispatcher.h>
34#include <wtf/Functional.h>
35#include <wtf/HashMap.h>
36#include <wtf/RetainPtr.h>
37#include <wtf/Threading.h>
38
39#if USE(GLIB)
40#include <wtf/gobject/GMainLoopSource.h>
41#endif
42
43#if PLATFORM(EFL)
44#include <Ecore.h>
45#include <wtf/efl/UniquePtrEfl.h>
46#endif
47
48namespace WTF {
49
50class RunLoop : public FunctionDispatcher {
51    WTF_MAKE_NONCOPYABLE(RunLoop);
52public:
53    // Must be called from the main thread (except for the Mac platform, where it
54    // can be called from any thread).
55    WTF_EXPORT_PRIVATE static void initializeMainRunLoop();
56
57    WTF_EXPORT_PRIVATE static RunLoop& current();
58    WTF_EXPORT_PRIVATE static RunLoop& main();
59    WTF_EXPORT_PRIVATE static bool isMain();
60    ~RunLoop();
61
62    virtual void dispatch(std::function<void()>) override;
63
64    WTF_EXPORT_PRIVATE static void run();
65    WTF_EXPORT_PRIVATE void stop();
66    WTF_EXPORT_PRIVATE void wakeUp();
67
68#if PLATFORM(COCOA)
69    WTF_EXPORT_PRIVATE void runForDuration(double duration);
70#endif
71
72    class TimerBase {
73        friend class RunLoop;
74    public:
75        WTF_EXPORT_PRIVATE explicit TimerBase(RunLoop&);
76        WTF_EXPORT_PRIVATE virtual ~TimerBase();
77
78        void startRepeating(double repeatInterval) { start(repeatInterval, true); }
79        void startRepeating(std::chrono::milliseconds repeatInterval) { startRepeating(repeatInterval.count() * 0.001); }
80        void startOneShot(double interval) { start(interval, false); }
81
82        WTF_EXPORT_PRIVATE void stop();
83        WTF_EXPORT_PRIVATE bool isActive() const;
84
85        virtual void fired() = 0;
86
87    private:
88        WTF_EXPORT_PRIVATE void start(double nextFireInterval, bool repeat);
89
90        RunLoop& m_runLoop;
91
92#if PLATFORM(WIN)
93        static void timerFired(RunLoop*, uint64_t ID);
94        uint64_t m_ID;
95        bool m_isRepeating;
96#elif PLATFORM(COCOA)
97        static void timerFired(CFRunLoopTimerRef, void*);
98        RetainPtr<CFRunLoopTimerRef> m_timer;
99#elif PLATFORM(EFL)
100        static bool timerFired(void* data);
101        Ecore_Timer* m_timer;
102        bool m_isRepeating;
103#elif USE(GLIB)
104        GMainLoopSource m_timerSource;
105#endif
106    };
107
108    template <typename TimerFiredClass>
109    class Timer : public TimerBase {
110    public:
111        typedef void (TimerFiredClass::*TimerFiredFunction)();
112
113        Timer(RunLoop& runLoop, TimerFiredClass* o, TimerFiredFunction f)
114            : TimerBase(runLoop)
115            , m_object(o)
116            , m_function(f)
117        {
118        }
119
120    private:
121        virtual void fired() { (m_object->*m_function)(); }
122
123        TimerFiredClass* m_object;
124        TimerFiredFunction m_function;
125    };
126
127    class Holder;
128
129private:
130    RunLoop();
131
132    void performWork();
133
134    Mutex m_functionQueueLock;
135    Deque<std::function<void ()>> m_functionQueue;
136
137#if PLATFORM(WIN)
138    static bool registerRunLoopMessageWindowClass();
139    static LRESULT CALLBACK RunLoopWndProc(HWND, UINT, WPARAM, LPARAM);
140    LRESULT wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
141    HWND m_runLoopMessageWindow;
142
143    typedef HashMap<uint64_t, TimerBase*> TimerMap;
144    TimerMap m_activeTimers;
145#elif PLATFORM(COCOA)
146    static void performWork(void*);
147    RetainPtr<CFRunLoopRef> m_runLoop;
148    RetainPtr<CFRunLoopSourceRef> m_runLoopSource;
149    int m_nestingLevel;
150#elif PLATFORM(EFL)
151    Mutex m_pipeLock;
152    EflUniquePtr<Ecore_Pipe> m_pipe;
153
154    Mutex m_wakeUpEventRequestedLock;
155    bool m_wakeUpEventRequested;
156
157    static void wakeUpEvent(void* data, void*, unsigned);
158#elif USE(GLIB)
159public:
160    static gboolean queueWork(RunLoop*);
161    GMainLoop* innermostLoop();
162    void pushNestedMainLoop(GMainLoop*);
163    void popNestedMainLoop();
164private:
165    GRefPtr<GMainContext> m_runLoopContext;
166    Vector<GRefPtr<GMainLoop>> m_runLoopMainLoops;
167#endif
168};
169
170} // namespace WTF
171
172using WTF::RunLoop;
173
174#endif // RunLoop_h
175