WebKit fixes to enable -Wstrict-prototypes for Safari
[WebKit.git] / Source / WebCore / platform / ios / wak / WebCoreThreadRun.cpp
1 /*
2  * Copyright (C) 2010, 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WebCoreThreadRun.h"
28
29 #if PLATFORM(IOS)
30
31 #include "WebCoreThreadInternal.h"
32 #include <mutex>
33 #include <wtf/Condition.h>
34 #include <wtf/Lock.h>
35 #include <wtf/Vector.h>
36
37 namespace {
38
39 class WebThreadBlockState {
40 public:
41     WebThreadBlockState()
42         : m_completed(false)
43     {
44     }
45
46     void waitForCompletion()
47     {
48         std::unique_lock<Lock> lock(m_stateMutex);
49
50         m_completionConditionVariable.wait(lock, [this] { return m_completed; });
51     }
52
53     void setCompleted()
54     {
55         std::lock_guard<Lock> lock(m_stateMutex);
56
57         ASSERT(!m_completed);
58         m_completed = true;
59         m_completionConditionVariable.notifyOne();
60     }
61
62 private:
63     Lock m_stateMutex;
64     Condition m_completionConditionVariable;
65     bool m_completed;
66 };
67
68 class WebThreadBlock {
69 public:
70     WebThreadBlock(void (^block)(void), WebThreadBlockState* state)
71         : m_block(Block_copy(block))
72         , m_state(state)
73     {
74     }
75
76     WebThreadBlock(const WebThreadBlock& other)
77         : m_block(Block_copy(other.m_block))
78         , m_state(other.m_state)
79     {
80     }
81
82     WebThreadBlock& operator=(const WebThreadBlock& other)
83     {
84         void (^oldBlock)() = m_block;
85         m_block = Block_copy(other.m_block);
86         Block_release(oldBlock);
87         m_state = other.m_state;
88         return *this;
89     }
90
91     ~WebThreadBlock()
92     {
93         Block_release(m_block);
94     }
95
96     void operator()() const
97     {
98         m_block();
99         if (m_state)
100             m_state->setCompleted();
101     }
102
103 private:
104     void (^m_block)(void);
105     WebThreadBlockState* m_state;
106 };
107
108 }
109
110 extern "C" {
111
112 typedef WTF::Vector<WebThreadBlock> WebThreadRunQueue;
113
114 static StaticLock runQueueMutex;
115 static CFRunLoopSourceRef runSource;
116 static WebThreadRunQueue* runQueue;
117
118 static void HandleRunSource(void *info)
119 {
120     UNUSED_PARAM(info);
121     ASSERT(WebThreadIsCurrent());
122     ASSERT(runSource);
123     ASSERT(runQueue);
124
125     WebThreadRunQueue queueCopy;
126     {
127         std::lock_guard<StaticLock> lock(runQueueMutex);
128         queueCopy = *runQueue;
129         runQueue->clear();
130     }
131
132     for (const auto& block : queueCopy)
133         block();
134 }
135
136 static void _WebThreadRun(void (^block)(void), bool synchronous)
137 {
138     if (WebThreadIsCurrent() || !WebThreadIsEnabled()) {
139         block();
140         return;
141     }
142
143     ASSERT(runSource);
144     ASSERT(runQueue);
145
146     WebThreadBlockState* state = 0;
147     if (synchronous)
148         state = new WebThreadBlockState;
149
150     {
151         std::lock_guard<StaticLock> lock(runQueueMutex);
152         runQueue->append(WebThreadBlock(block, state));
153     }
154
155     CFRunLoopSourceSignal(runSource);
156     CFRunLoopWakeUp(WebThreadRunLoop());
157
158     if (synchronous) {
159         state->waitForCompletion();
160         delete state;
161     }
162 }
163
164 void WebThreadRun(void (^block)(void))
165 {
166     _WebThreadRun(block, false);
167 }
168
169 void WebThreadInitRunQueue()
170 {
171     ASSERT(!runQueue);
172     ASSERT(!runSource);
173
174     static dispatch_once_t pred;
175     dispatch_once(&pred, ^{
176         runQueue = new WebThreadRunQueue;
177
178         CFRunLoopSourceContext runSourceContext = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, HandleRunSource};
179         runSource = CFRunLoopSourceCreate(NULL, -1, &runSourceContext);
180         CFRunLoopAddSource(WebThreadRunLoop(), runSource, kCFRunLoopDefaultMode);
181     });
182 }
183
184 }
185
186 #endif // PLATFORM(IOS)