WorkQueueGeneric's platformInvalidate() can deadlock when called on the RunLoop's...
[WebKit-https.git] / Source / WTF / wtf / WorkQueue.h
1 /*
2  * Copyright (C) 2010, 2015 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 #include <chrono>
31 #include <functional>
32 #include <wtf/Forward.h>
33 #include <wtf/FunctionDispatcher.h>
34 #include <wtf/RefCounted.h>
35 #include <wtf/Threading.h>
36
37 #if USE(COCOA_EVENT_LOOP)
38 #include <dispatch/dispatch.h>
39 #endif
40
41 #if USE(EFL_EVENT_LOOP)
42 #include <DispatchQueueEfl.h>
43 #endif
44
45 #if USE(WINDOWS_EVENT_LOOP)
46 #include <wtf/Vector.h>
47 #endif
48
49 #if USE(GLIB_EVENT_LOOP) || USE(GENERIC_EVENT_LOOP)
50 #include <wtf/Condition.h>
51 #include <wtf/RunLoop.h>
52 #endif
53
54 namespace WTF {
55
56 class WorkQueue final : public FunctionDispatcher {
57 public:
58     enum class Type {
59         Serial,
60         Concurrent
61     };
62     enum class QOS {
63         UserInteractive,
64         UserInitiated,
65         Default,
66         Utility,
67         Background
68     };
69
70     WTF_EXPORT_PRIVATE static Ref<WorkQueue> create(const char* name, Type = Type::Serial, QOS = QOS::Default);
71     virtual ~WorkQueue();
72
73     WTF_EXPORT_PRIVATE void dispatch(Function<void ()>&&) override;
74     WTF_EXPORT_PRIVATE void dispatchAfter(std::chrono::nanoseconds, Function<void ()>&&);
75
76     WTF_EXPORT_PRIVATE static void concurrentApply(size_t iterations, const std::function<void (size_t index)>&);
77
78 #if USE(EFL_EVENT_LOOP)
79     void registerSocketEventHandler(int, std::function<void ()>);
80     void unregisterSocketEventHandler(int);
81 #elif USE(COCOA_EVENT_LOOP)
82     dispatch_queue_t dispatchQueue() const { return m_dispatchQueue; }
83 #elif USE(GLIB_EVENT_LOOP) || USE(GENERIC_EVENT_LOOP)
84     RunLoop& runLoop() const { return *m_runLoop; }
85 #endif
86
87 private:
88     explicit WorkQueue(const char* name, Type, QOS);
89
90     void platformInitialize(const char* name, Type, QOS);
91     void platformInvalidate();
92
93 #if USE(WINDOWS_EVENT_LOOP)
94     static void CALLBACK timerCallback(void* context, BOOLEAN timerOrWaitFired);
95     static DWORD WINAPI workThreadCallback(void* context);
96
97     bool tryRegisterAsWorkThread();
98     void unregisterAsWorkThread();
99     void performWorkOnRegisteredWorkThread();
100 #endif
101
102 #if USE(EFL_EVENT_LOOP)
103     RefPtr<DispatchQueue> m_dispatchQueue;
104 #elif USE(COCOA_EVENT_LOOP)
105     static void executeFunction(void*);
106     dispatch_queue_t m_dispatchQueue;
107 #elif USE(WINDOWS_EVENT_LOOP)
108     volatile LONG m_isWorkThreadRegistered;
109
110     Mutex m_functionQueueLock;
111     Vector<Function<void ()>> m_functionQueue;
112
113     HANDLE m_timerQueue;
114 #elif USE(GLIB_EVENT_LOOP) || USE(GENERIC_EVENT_LOOP)
115     ThreadIdentifier m_workQueueThread;
116     Lock m_initializeRunLoopConditionMutex;
117     Condition m_initializeRunLoopCondition;
118     RunLoop* m_runLoop;
119 #endif
120 };
121
122 }
123
124 using WTF::WorkQueue;
125
126 #endif