1/* 2 * Copyright (C) 2010 Apple Inc. All rights reserved. 3 * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved. 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#ifndef WorkQueue_h 28#define WorkQueue_h 29 30#if OS(DARWIN) 31#if HAVE(DISPATCH_H) 32#include <dispatch/dispatch.h> 33#endif 34#endif 35 36#include <wtf/Forward.h> 37#include <wtf/Functional.h> 38#include <wtf/HashMap.h> 39#include <wtf/PassOwnPtr.h> 40#include <wtf/RefCounted.h> 41#include <wtf/Threading.h> 42#include <wtf/Vector.h> 43 44#if (PLATFORM(QT) && !OS(DARWIN)) || PLATFORM(GTK) || PLATFORM(EFL) 45#include "PlatformProcessIdentifier.h" 46#endif 47 48#if PLATFORM(QT) && !OS(DARWIN) 49#include <QSocketNotifier> 50QT_BEGIN_NAMESPACE 51class QObject; 52class QThread; 53QT_END_NAMESPACE 54#elif PLATFORM(GTK) 55#include <wtf/gobject/GRefPtr.h> 56typedef gboolean (*GSourceFunc) (gpointer data); 57#elif PLATFORM(EFL) 58#include <Ecore.h> 59#endif 60 61class WorkQueue : public ThreadSafeRefCounted<WorkQueue> { 62public: 63 static PassRefPtr<WorkQueue> create(const char* name); 64 ~WorkQueue(); 65 66 // Will dispatch the given function to run as soon as possible. 67 void dispatch(const Function<void()>&); 68 69 // Will dispatch the given function after the given delay (in seconds). 70 void dispatchAfterDelay(const Function<void()>&, double delay); 71 72#if OS(DARWIN) 73 dispatch_queue_t dispatchQueue() const { return m_dispatchQueue; } 74 75#elif OS(WINDOWS) 76 void registerHandle(HANDLE, const Function<void()>&); 77 void unregisterAndCloseHandle(HANDLE); 78#elif PLATFORM(QT) 79 QSocketNotifier* registerSocketEventHandler(int, QSocketNotifier::Type, const Function<void()>&); 80 void dispatchOnTermination(WebKit::PlatformProcessIdentifier, const Function<void()>&); 81#elif PLATFORM(GTK) 82 void registerSocketEventHandler(int, int, const Function<void()>& function, const Function<void()>& closeFunction); 83 void unregisterSocketEventHandler(int); 84 void dispatchOnTermination(WebKit::PlatformProcessIdentifier, const Function<void()>&); 85#elif PLATFORM(EFL) 86 void registerSocketEventHandler(int, const Function<void()>&); 87 void unregisterSocketEventHandler(int); 88#endif 89 90private: 91 explicit WorkQueue(const char* name); 92 93 void platformInitialize(const char* name); 94 void platformInvalidate(); 95 96#if OS(DARWIN) 97 static void executeFunction(void*); 98 dispatch_queue_t m_dispatchQueue; 99#elif OS(WINDOWS) 100 class WorkItemWin : public ThreadSafeRefCounted<WorkItemWin> { 101 public: 102 static PassRefPtr<WorkItemWin> create(const Function<void()>&, WorkQueue*); 103 virtual ~WorkItemWin(); 104 105 Function<void()>& function() { return m_function; } 106 WorkQueue* queue() const { return m_queue.get(); } 107 108 protected: 109 WorkItemWin(const Function<void()>&, WorkQueue*); 110 111 private: 112 Function<void()> m_function; 113 RefPtr<WorkQueue> m_queue; 114 }; 115 116 class HandleWorkItem : public WorkItemWin { 117 public: 118 static PassRefPtr<HandleWorkItem> createByAdoptingHandle(HANDLE, const Function<void()>&, WorkQueue*); 119 virtual ~HandleWorkItem(); 120 121 void setWaitHandle(HANDLE waitHandle) { m_waitHandle = waitHandle; } 122 HANDLE waitHandle() const { return m_waitHandle; } 123 124 private: 125 HandleWorkItem(HANDLE, const Function<void()>&, WorkQueue*); 126 127 HANDLE m_handle; 128 HANDLE m_waitHandle; 129 }; 130 131 static void CALLBACK handleCallback(void* context, BOOLEAN timerOrWaitFired); 132 static void CALLBACK timerCallback(void* context, BOOLEAN timerOrWaitFired); 133 static DWORD WINAPI workThreadCallback(void* context); 134 135 bool tryRegisterAsWorkThread(); 136 void unregisterAsWorkThread(); 137 void performWorkOnRegisteredWorkThread(); 138 139 static void unregisterWaitAndDestroyItemSoon(PassRefPtr<HandleWorkItem>); 140 static DWORD WINAPI unregisterWaitAndDestroyItemCallback(void* context); 141 142 volatile LONG m_isWorkThreadRegistered; 143 144 Mutex m_workItemQueueLock; 145 Vector<RefPtr<WorkItemWin>> m_workItemQueue; 146 147 Mutex m_handlesLock; 148 HashMap<HANDLE, RefPtr<HandleWorkItem>> m_handles; 149 150 HANDLE m_timerQueue; 151#elif PLATFORM(QT) 152 class WorkItemQt; 153 QThread* m_workThread; 154 friend class WorkItemQt; 155#elif PLATFORM(GTK) 156 static void startWorkQueueThread(WorkQueue*); 157 void workQueueThreadBody(); 158 void dispatchOnSource(GSource*, const Function<void()>&, GSourceFunc); 159 160 ThreadIdentifier m_workQueueThread; 161 GRefPtr<GMainContext> m_eventContext; 162 Mutex m_eventLoopLock; 163 GRefPtr<GMainLoop> m_eventLoop; 164 Mutex m_eventSourcesLock; 165 class EventSource; 166 class SocketEventSource; 167 HashMap<int, Vector<SocketEventSource*>> m_eventSources; 168 typedef HashMap<int, Vector<SocketEventSource*>>::iterator SocketEventSourceIterator; 169#elif PLATFORM(EFL) 170 class TimerWorkItem { 171 public: 172 static PassOwnPtr<TimerWorkItem> create(Function<void()>, double expireTime); 173 void dispatch() { m_function(); } 174 double expireTime() const { return m_expireTime; } 175 bool expired(double currentTime) const { return currentTime >= m_expireTime; } 176 177 protected: 178 TimerWorkItem(Function<void()>, double expireTime); 179 180 private: 181 Function<void()> m_function; 182 double m_expireTime; 183 }; 184 185 fd_set m_fileDescriptorSet; 186 int m_maxFileDescriptor; 187 int m_readFromPipeDescriptor; 188 int m_writeToPipeDescriptor; 189 Mutex m_writeToPipeDescriptorLock; 190 191 bool m_threadLoop; 192 193 Vector<Function<void()>> m_workItemQueue; 194 Mutex m_workItemQueueLock; 195 196 int m_socketDescriptor; 197 Function<void()> m_socketEventHandler; 198 199 Vector<OwnPtr<TimerWorkItem>> m_timerWorkItems; 200 Mutex m_timerWorkItemsLock; 201 202 void sendMessageToThread(const char*); 203 static void* workQueueThread(WorkQueue*); 204 void performWork(); 205 void performFileDescriptorWork(); 206 static double getCurrentTime(); 207 struct timeval* getNextTimeOut(); 208 void performTimerWork(); 209 void insertTimerWorkItem(PassOwnPtr<TimerWorkItem>); 210#endif 211}; 212 213#endif // WorkQueue_h 214