1/*
2 * Copyright (C) 2012, 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 "ScrollingThread.h"
28
29#if ENABLE(ASYNC_SCROLLING)
30
31#include <mutex>
32#include <wtf/MainThread.h>
33#include <wtf/NeverDestroyed.h>
34
35namespace WebCore {
36
37ScrollingThread::ScrollingThread()
38{
39}
40
41bool ScrollingThread::isCurrentThread()
42{
43 return ScrollingThread::singleton().m_thread == &Thread::current();
44}
45
46void ScrollingThread::dispatch(Function<void ()>&& function)
47{
48 auto& scrollingThread = ScrollingThread::singleton();
49 scrollingThread.createThreadIfNeeded();
50
51 {
52 std::lock_guard<Lock> lock(scrollingThread.m_functionsMutex);
53 scrollingThread.m_functions.append(WTFMove(function));
54 }
55
56 scrollingThread.wakeUpRunLoop();
57}
58
59void ScrollingThread::dispatchBarrier(Function<void ()>&& function)
60{
61 dispatch([function = WTFMove(function)]() mutable {
62 callOnMainThread(WTFMove(function));
63 });
64}
65
66ScrollingThread& ScrollingThread::singleton()
67{
68 static NeverDestroyed<ScrollingThread> scrollingThread;
69
70 return scrollingThread;
71}
72
73void ScrollingThread::createThreadIfNeeded()
74{
75 // Wait for the thread to initialize the run loop.
76 std::unique_lock<Lock> lock(m_initializeRunLoopMutex);
77
78 if (!m_thread) {
79 m_thread = Thread::create("WebCore: Scrolling", [this] {
80 WTF::Thread::setCurrentThreadIsUserInteractive();
81 initializeRunLoop();
82 });
83 }
84
85#if PLATFORM(COCOA)
86 m_initializeRunLoopConditionVariable.wait(lock, [this]{ return m_threadRunLoop; });
87#else
88 m_initializeRunLoopConditionVariable.wait(lock, [this]{ return m_runLoop; });
89#endif
90}
91
92void ScrollingThread::dispatchFunctionsFromScrollingThread()
93{
94 ASSERT(isCurrentThread());
95
96 Vector<Function<void ()>> functions;
97
98 {
99 std::lock_guard<Lock> lock(m_functionsMutex);
100 functions = WTFMove(m_functions);
101 }
102
103 for (auto& function : functions)
104 function();
105}
106
107#if PLATFORM(IOS_FAMILY)
108NO_RETURN_DUE_TO_ASSERT void ScrollingThread::initializeRunLoop()
109{
110 ASSERT_NOT_REACHED();
111}
112
113void ScrollingThread::wakeUpRunLoop()
114{
115}
116
117void ScrollingThread::threadRunLoopSourceCallback(void*)
118{
119}
120
121void ScrollingThread::threadRunLoopSourceCallback()
122{
123}
124#endif // PLATFORM(IOS_FAMILY)
125
126} // namespace WebCore
127
128#endif // ENABLE(ASYNC_SCROLLING)
129