Home | History | Annotate | Download | only in Platform
      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 PLATFORM(MAC)
     31 #if HAVE(DISPATCH_H)
     32 #include <dispatch/dispatch.h>
     33 #endif
     34 #endif
     35 
     36 #include "WorkItem.h"
     37 #include <wtf/HashMap.h>
     38 #include <wtf/PassOwnPtr.h>
     39 #include <wtf/RefCounted.h>
     40 #include <wtf/Threading.h>
     41 #include <wtf/Vector.h>
     42 
     43 #if PLATFORM(QT)
     44 #include <QSocketNotifier>
     45 #include "PlatformProcessIdentifier.h"
     46 class QObject;
     47 class QThread;
     48 #elif PLATFORM(GTK)
     49 #include "PlatformProcessIdentifier.h"
     50 typedef struct _GMainContext GMainContext;
     51 typedef struct _GMainLoop GMainLoop;
     52 typedef gboolean (*GSourceFunc) (gpointer data);
     53 #endif
     54 
     55 class WorkQueue {
     56     WTF_MAKE_NONCOPYABLE(WorkQueue);
     57 
     58 public:
     59     explicit WorkQueue(const char* name);
     60     ~WorkQueue();
     61 
     62     // Will schedule the given work item to run as soon as possible.
     63     void scheduleWork(PassOwnPtr<WorkItem>);
     64 
     65     // Will schedule the given work item to run after the given delay (in seconds).
     66     void scheduleWorkAfterDelay(PassOwnPtr<WorkItem>, double delay);
     67 
     68     void invalidate();
     69 
     70 #if PLATFORM(MAC)
     71     enum MachPortEventType {
     72         // Fired when there is data on the given receive right.
     73         MachPortDataAvailable,
     74 
     75         // Fired when the receive right for this send right has been destroyed.
     76         MachPortDeadNameNotification
     77     };
     78 
     79     // Will execute the given work item whenever the given mach port event fires.
     80     // Note that this will adopt the mach port and destroy it when the work queue is invalidated.
     81     void registerMachPortEventHandler(mach_port_t, MachPortEventType, PassOwnPtr<WorkItem>);
     82     void unregisterMachPortEventHandler(mach_port_t);
     83 #elif PLATFORM(WIN)
     84     void registerHandle(HANDLE, PassOwnPtr<WorkItem>);
     85     void unregisterAndCloseHandle(HANDLE);
     86 #elif PLATFORM(QT)
     87     QSocketNotifier* registerSocketEventHandler(int, QSocketNotifier::Type, PassOwnPtr<WorkItem>);
     88     void scheduleWorkOnTermination(WebKit::PlatformProcessIdentifier, PassOwnPtr<WorkItem>);
     89 #elif PLATFORM(GTK)
     90     void registerEventSourceHandler(int, int, PassOwnPtr<WorkItem>);
     91     void unregisterEventSourceHandler(int);
     92     void scheduleWorkOnTermination(WebKit::PlatformProcessIdentifier, PassOwnPtr<WorkItem>);
     93 #endif
     94 
     95 private:
     96     // FIXME: Use an atomic boolean here instead.
     97     Mutex m_isValidMutex;
     98     bool m_isValid;
     99 
    100     void platformInitialize(const char* name);
    101     void platformInvalidate();
    102 
    103 #if PLATFORM(MAC)
    104 #if HAVE(DISPATCH_H)
    105     static void executeWorkItem(void*);
    106     Mutex m_eventSourcesMutex;
    107     class EventSource;
    108     HashMap<mach_port_t, EventSource*> m_eventSources;
    109     dispatch_queue_t m_dispatchQueue;
    110 #endif
    111 #elif PLATFORM(WIN)
    112     class WorkItemWin : public ThreadSafeRefCounted<WorkItemWin> {
    113     public:
    114         static PassRefPtr<WorkItemWin> create(PassOwnPtr<WorkItem>, WorkQueue*);
    115         virtual ~WorkItemWin();
    116 
    117         WorkItem* item() const { return m_item.get(); }
    118         WorkQueue* queue() const { return m_queue; }
    119 
    120     protected:
    121         WorkItemWin(PassOwnPtr<WorkItem>, WorkQueue*);
    122 
    123     private:
    124         OwnPtr<WorkItem> m_item;
    125         WorkQueue* m_queue;
    126     };
    127 
    128     class HandleWorkItem : public WorkItemWin {
    129     public:
    130         static PassRefPtr<HandleWorkItem> createByAdoptingHandle(HANDLE, PassOwnPtr<WorkItem>, WorkQueue*);
    131         virtual ~HandleWorkItem();
    132 
    133         void setWaitHandle(HANDLE waitHandle) { m_waitHandle = waitHandle; }
    134         HANDLE waitHandle() const { return m_waitHandle; }
    135 
    136     private:
    137         HandleWorkItem(HANDLE, PassOwnPtr<WorkItem>, WorkQueue*);
    138 
    139         HANDLE m_handle;
    140         HANDLE m_waitHandle;
    141     };
    142 
    143     static void CALLBACK handleCallback(void* context, BOOLEAN timerOrWaitFired);
    144     static void CALLBACK timerCallback(void* context, BOOLEAN timerOrWaitFired);
    145     static DWORD WINAPI workThreadCallback(void* context);
    146 
    147     bool tryRegisterAsWorkThread();
    148     void unregisterAsWorkThread();
    149     void performWorkOnRegisteredWorkThread();
    150 
    151     static void unregisterWaitAndDestroyItemSoon(PassRefPtr<HandleWorkItem>);
    152     static DWORD WINAPI unregisterWaitAndDestroyItemCallback(void* context);
    153 
    154     volatile LONG m_isWorkThreadRegistered;
    155 
    156     Mutex m_workItemQueueLock;
    157     Vector<RefPtr<WorkItemWin> > m_workItemQueue;
    158 
    159     Mutex m_handlesLock;
    160     HashMap<HANDLE, RefPtr<HandleWorkItem> > m_handles;
    161 
    162     HANDLE m_timerQueue;
    163 #elif PLATFORM(QT)
    164     class WorkItemQt;
    165     HashMap<QObject*, WorkItemQt*> m_signalListeners;
    166     QThread* m_workThread;
    167     friend class WorkItemQt;
    168 #elif PLATFORM(GTK)
    169     static void* startWorkQueueThread(WorkQueue*);
    170     void workQueueThreadBody();
    171     void scheduleWorkOnSource(GSource*, PassOwnPtr<WorkItem>, GSourceFunc);
    172 
    173     ThreadIdentifier m_workQueueThread;
    174     GMainContext* m_eventContext;
    175     Mutex m_eventLoopLock;
    176     GMainLoop* m_eventLoop;
    177     Mutex m_eventSourcesLock;
    178     class EventSource;
    179     HashMap<int, Vector<EventSource*> > m_eventSources;
    180     typedef HashMap<int, Vector<EventSource*> >::iterator EventSourceIterator;
    181 #endif
    182 };
    183 
    184 #endif // WorkQueue_h
    185