/* * Copyright (C) 2010 Apple Inc. All rights reserved. * 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 WorkQueue_h #define WorkQueue_h #if OS(DARWIN) #if HAVE(DISPATCH_H) #include #endif #endif #include #include #include #include #include #include #include #if (PLATFORM(QT) && !OS(DARWIN)) || PLATFORM(GTK) || PLATFORM(EFL) #include "PlatformProcessIdentifier.h" #endif #if PLATFORM(QT) && !OS(DARWIN) #include QT_BEGIN_NAMESPACE class QObject; class QThread; QT_END_NAMESPACE #elif PLATFORM(GTK) #include typedef gboolean (*GSourceFunc) (gpointer data); #elif PLATFORM(EFL) #include #endif class WorkQueue : public ThreadSafeRefCounted { public: static PassRefPtr create(const char* name); ~WorkQueue(); // Will dispatch the given function to run as soon as possible. void dispatch(const Function&); // Will dispatch the given function after the given delay (in seconds). void dispatchAfterDelay(const Function&, double delay); #if OS(DARWIN) dispatch_queue_t dispatchQueue() const { return m_dispatchQueue; } #elif OS(WINDOWS) void registerHandle(HANDLE, const Function&); void unregisterAndCloseHandle(HANDLE); #elif PLATFORM(QT) QSocketNotifier* registerSocketEventHandler(int, QSocketNotifier::Type, const Function&); void dispatchOnTermination(WebKit::PlatformProcessIdentifier, const Function&); #elif PLATFORM(GTK) void registerSocketEventHandler(int, int, const Function& function, const Function& closeFunction); void unregisterSocketEventHandler(int); void dispatchOnTermination(WebKit::PlatformProcessIdentifier, const Function&); #elif PLATFORM(EFL) void registerSocketEventHandler(int, const Function&); void unregisterSocketEventHandler(int); #endif private: explicit WorkQueue(const char* name); void platformInitialize(const char* name); void platformInvalidate(); #if OS(DARWIN) static void executeFunction(void*); dispatch_queue_t m_dispatchQueue; #elif OS(WINDOWS) class WorkItemWin : public ThreadSafeRefCounted { public: static PassRefPtr create(const Function&, WorkQueue*); virtual ~WorkItemWin(); Function& function() { return m_function; } WorkQueue* queue() const { return m_queue.get(); } protected: WorkItemWin(const Function&, WorkQueue*); private: Function m_function; RefPtr m_queue; }; class HandleWorkItem : public WorkItemWin { public: static PassRefPtr createByAdoptingHandle(HANDLE, const Function&, WorkQueue*); virtual ~HandleWorkItem(); void setWaitHandle(HANDLE waitHandle) { m_waitHandle = waitHandle; } HANDLE waitHandle() const { return m_waitHandle; } private: HandleWorkItem(HANDLE, const Function&, WorkQueue*); HANDLE m_handle; HANDLE m_waitHandle; }; static void CALLBACK handleCallback(void* context, BOOLEAN timerOrWaitFired); static void CALLBACK timerCallback(void* context, BOOLEAN timerOrWaitFired); static DWORD WINAPI workThreadCallback(void* context); bool tryRegisterAsWorkThread(); void unregisterAsWorkThread(); void performWorkOnRegisteredWorkThread(); static void unregisterWaitAndDestroyItemSoon(PassRefPtr); static DWORD WINAPI unregisterWaitAndDestroyItemCallback(void* context); volatile LONG m_isWorkThreadRegistered; Mutex m_workItemQueueLock; Vector> m_workItemQueue; Mutex m_handlesLock; HashMap> m_handles; HANDLE m_timerQueue; #elif PLATFORM(QT) class WorkItemQt; QThread* m_workThread; friend class WorkItemQt; #elif PLATFORM(GTK) static void startWorkQueueThread(WorkQueue*); void workQueueThreadBody(); void dispatchOnSource(GSource*, const Function&, GSourceFunc); ThreadIdentifier m_workQueueThread; GRefPtr m_eventContext; Mutex m_eventLoopLock; GRefPtr m_eventLoop; Mutex m_eventSourcesLock; class EventSource; class SocketEventSource; HashMap> m_eventSources; typedef HashMap>::iterator SocketEventSourceIterator; #elif PLATFORM(EFL) class TimerWorkItem { public: static PassOwnPtr create(Function, double expireTime); void dispatch() { m_function(); } double expireTime() const { return m_expireTime; } bool expired(double currentTime) const { return currentTime >= m_expireTime; } protected: TimerWorkItem(Function, double expireTime); private: Function m_function; double m_expireTime; }; fd_set m_fileDescriptorSet; int m_maxFileDescriptor; int m_readFromPipeDescriptor; int m_writeToPipeDescriptor; Mutex m_writeToPipeDescriptorLock; bool m_threadLoop; Vector> m_workItemQueue; Mutex m_workItemQueueLock; int m_socketDescriptor; Function m_socketEventHandler; Vector> m_timerWorkItems; Mutex m_timerWorkItemsLock; void sendMessageToThread(const char*); static void* workQueueThread(WorkQueue*); void performWork(); void performFileDescriptorWork(); static double getCurrentTime(); struct timeval* getNextTimeOut(); void performTimerWork(); void insertTimerWorkItem(PassOwnPtr); #endif }; #endif // WorkQueue_h