• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
item()117         WorkItem* item() const { return m_item.get(); }
queue()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 
setWaitHandle(HANDLE waitHandle)133         void setWaitHandle(HANDLE waitHandle) { m_waitHandle = 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