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 PLATFORM(GTK)
40#include <wtf/gobject/GRefPtr.h>
41#endif
42
43#if PLATFORM(EFL)
44#include <Ecore.h>
45#endif
46
47namespace WebCore {
48
49class RunLoop : public FunctionDispatcher {
50public:
51    // Must be called from the main thread (except for the Mac platform, where it
52    // can be called from any thread).
53    static void initializeMainRunLoop();
54
55    // Must be called before entering main run loop. If called, application style run loop will be used, handling events.
56    static void setUseApplicationRunLoopOnMainRunLoop();
57
58    static RunLoop* current();
59    static RunLoop* main();
60    ~RunLoop();
61
62    virtual void dispatch(const Function<void()>&) OVERRIDE;
63
64    static void run();
65    void stop();
66    void wakeUp();
67
68#if PLATFORM(MAC)
69    void runForDuration(double duration);
70#endif
71
72    class TimerBase {
73        friend class RunLoop;
74    public:
75        explicit TimerBase(RunLoop*);
76        virtual ~TimerBase();
77
78        void startRepeating(double repeatInterval) { start(repeatInterval, true); }
79        void startOneShot(double interval) { start(interval, false); }
80
81        void stop();
82        bool isActive() const;
83
84        virtual void fired() = 0;
85
86    private:
87        void start(double nextFireInterval, bool repeat);
88
89        RunLoop* m_runLoop;
90
91#if PLATFORM(WIN)
92        static void timerFired(RunLoop*, uint64_t ID);
93        uint64_t m_ID;
94        bool m_isRepeating;
95#elif PLATFORM(MAC)
96        static void timerFired(CFRunLoopTimerRef, void*);
97        RetainPtr<CFRunLoopTimerRef> m_timer;
98#elif PLATFORM(QT)
99        static void timerFired(RunLoop*, int ID);
100        int m_ID;
101        bool m_isRepeating;
102#elif PLATFORM(GTK)
103        static gboolean timerFiredCallback(RunLoop::TimerBase*);
104        gboolean isRepeating() const { return m_isRepeating; }
105        void clearTimerSource();
106        GRefPtr<GSource> m_timerSource;
107        gboolean m_isRepeating;
108#elif PLATFORM(EFL)
109        static bool timerFired(void* data);
110        Ecore_Timer* m_timer;
111        bool m_isRepeating;
112#endif
113    };
114
115    template <typename TimerFiredClass>
116    class Timer : public TimerBase {
117    public:
118        typedef void (TimerFiredClass::*TimerFiredFunction)();
119
120        Timer(RunLoop* runLoop, TimerFiredClass* o, TimerFiredFunction f)
121            : TimerBase(runLoop)
122            , m_object(o)
123            , m_function(f)
124        {
125        }
126
127    private:
128        virtual void fired() { (m_object->*m_function)(); }
129
130        TimerFiredClass* m_object;
131        TimerFiredFunction m_function;
132    };
133
134    class Holder;
135
136private:
137    RunLoop();
138
139    void performWork();
140
141    Mutex m_functionQueueLock;
142    Deque<Function<void()> > m_functionQueue;
143
144#if PLATFORM(WIN)
145    static bool registerRunLoopMessageWindowClass();
146    static LRESULT CALLBACK RunLoopWndProc(HWND, UINT, WPARAM, LPARAM);
147    LRESULT wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
148    HWND m_runLoopMessageWindow;
149
150    typedef HashMap<uint64_t, TimerBase*> TimerMap;
151    TimerMap m_activeTimers;
152#elif PLATFORM(MAC)
153    static void performWork(void*);
154    RetainPtr<CFRunLoopRef> m_runLoop;
155    RetainPtr<CFRunLoopSourceRef> m_runLoopSource;
156    int m_nestingLevel;
157#elif PLATFORM(QT)
158    typedef HashMap<int, TimerBase*> TimerMap;
159    TimerMap m_activeTimers;
160    class TimerObject;
161    TimerObject* m_timerObject;
162#elif PLATFORM(GTK)
163public:
164    static gboolean queueWork(RunLoop*);
165    GMainLoop* innermostLoop();
166    void pushNestedMainLoop(GMainLoop*);
167    void popNestedMainLoop();
168private:
169    GRefPtr<GMainContext> m_runLoopContext;
170    Vector<GRefPtr<GMainLoop> > m_runLoopMainLoops;
171#elif PLATFORM(EFL)
172    bool m_initEfl;
173
174    Mutex m_pipeLock;
175    OwnPtr<Ecore_Pipe> m_pipe;
176
177    Mutex m_wakeUpEventRequestedLock;
178    bool m_wakeUpEventRequested;
179
180    static void wakeUpEvent(void* data, void*, unsigned int);
181#endif
182};
183
184} // namespace WebCore
185
186#endif // RunLoop_h
187