[WTF] Add WorkerPool
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 8 Jun 2018 08:47:06 +0000 (08:47 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 8 Jun 2018 08:47:06 +0000 (08:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=174569

Reviewed by Carlos Garcia Campos.

Source/WebCore:

We start using WorkerPool for NicosiaPaintingEngineThreaded instead of glib thread pool.
This makes NicosiaPaintingEngineThreaded platform-independent and usable for WinCairo.

* platform/graphics/nicosia/NicosiaPaintingEngineThreaded.cpp:
(Nicosia::PaintingEngineThreaded::PaintingEngineThreaded):
(Nicosia::PaintingEngineThreaded::~PaintingEngineThreaded):
(Nicosia::PaintingEngineThreaded::paint):
(Nicosia::s_threadFunc): Deleted.
* platform/graphics/nicosia/NicosiaPaintingEngineThreaded.h:

Source/WTF:

This patch adds WorkerPool, which is a thread pool that consists of AutomaticThread.
Since it is based on AutomaticThread, this WorkerPool can take `timeout`: once `timeout`
passes without any tasks, threads in WorkerPool will be destroyed.

We add shouldSleep handler to AutomaticThread to make destruction of threads in WorkerPool moderate.
Without this, all threads are destroyed at once after `timeout` passes.

* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::AutomaticThread):
(WTF::AutomaticThread::start):
* wtf/AutomaticThread.h:
* wtf/CMakeLists.txt:
* wtf/WorkerPool.cpp: Added.
(WTF::WorkerPool::WorkerPool):
(WTF::WorkerPool::~WorkerPool):
(WTF::WorkerPool::shouldSleep):
(WTF::WorkerPool::postTask):
* wtf/WorkerPool.h: Added.
(WTF::WorkerPool::create):

Tools:

* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/WorkerPool.cpp: Added.
(TestWebKitAPI::TEST):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232619 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
Source/WTF/ChangeLog
Source/WTF/WTF.xcodeproj/project.pbxproj
Source/WTF/wtf/AutomaticThread.cpp
Source/WTF/wtf/AutomaticThread.h
Source/WTF/wtf/CMakeLists.txt
Source/WTF/wtf/WorkerPool.cpp [new file with mode: 0644]
Source/WTF/wtf/WorkerPool.h [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/nicosia/NicosiaPaintingEngineThreaded.cpp
Source/WebCore/platform/graphics/nicosia/NicosiaPaintingEngineThreaded.h
Tools/ChangeLog
Tools/TestWebKitAPI/CMakeLists.txt
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WTF/WorkerPool.cpp [new file with mode: 0644]

index 82b8e70..9bbd049 100644 (file)
@@ -1,3 +1,31 @@
+2018-06-07  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [WTF] Add WorkerPool
+        https://bugs.webkit.org/show_bug.cgi?id=174569
+
+        Reviewed by Carlos Garcia Campos.
+
+        This patch adds WorkerPool, which is a thread pool that consists of AutomaticThread.
+        Since it is based on AutomaticThread, this WorkerPool can take `timeout`: once `timeout`
+        passes without any tasks, threads in WorkerPool will be destroyed.
+
+        We add shouldSleep handler to AutomaticThread to make destruction of threads in WorkerPool moderate.
+        Without this, all threads are destroyed at once after `timeout` passes.
+
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/AutomaticThread.cpp:
+        (WTF::AutomaticThread::AutomaticThread):
+        (WTF::AutomaticThread::start):
+        * wtf/AutomaticThread.h:
+        * wtf/CMakeLists.txt:
+        * wtf/WorkerPool.cpp: Added.
+        (WTF::WorkerPool::WorkerPool):
+        (WTF::WorkerPool::~WorkerPool):
+        (WTF::WorkerPool::shouldSleep):
+        (WTF::WorkerPool::postTask):
+        * wtf/WorkerPool.h: Added.
+        (WTF::WorkerPool::create):
+
 2018-06-07  Chris Dumez  <cdumez@apple.com>
 
         Add base class to get WeakPtrFactory member and avoid some boilerplate code
index 647a910..fb2ee7e 100644 (file)
                DCEE22011CEA7551000C2396 /* BlockObjCExceptions.mm in Sources */ = {isa = PBXBuildFile; fileRef = DCEE21FD1CEA7551000C2396 /* BlockObjCExceptions.mm */; };
                E15556F518A0CC18006F48FB /* CryptographicUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E15556F318A0CC18006F48FB /* CryptographicUtilities.cpp */; };
                E311FB171F0A568B003C08DE /* ThreadGroup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E311FB151F0A568B003C08DE /* ThreadGroup.cpp */; };
+               E388886F20C9095100E632BC /* WorkerPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E388886D20C9095100E632BC /* WorkerPool.cpp */; };
                E38C41251EB4E04C0042957D /* CPUTimeCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = E38C41241EB4E04C0042957D /* CPUTimeCocoa.mm */; };
                E38C41281EB4E0680042957D /* CPUTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38C41261EB4E0680042957D /* CPUTime.cpp */; };
                E38D6E271F5522E300A75CC4 /* StringBuilderJSON.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38D6E261F5522E300A75CC4 /* StringBuilderJSON.cpp */; };
                E311FB161F0A568B003C08DE /* ThreadGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadGroup.h; sourceTree = "<group>"; };
                E3200AB41E9A536D003B59D2 /* PlatformRegisters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformRegisters.h; sourceTree = "<group>"; };
                E33D5F871FBED66700BF625E /* RecursableLambda.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecursableLambda.h; sourceTree = "<group>"; };
+               E388886D20C9095100E632BC /* WorkerPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WorkerPool.cpp; sourceTree = "<group>"; };
+               E388886E20C9095100E632BC /* WorkerPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WorkerPool.h; sourceTree = "<group>"; };
                E38C41241EB4E04C0042957D /* CPUTimeCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CPUTimeCocoa.mm; sourceTree = "<group>"; };
                E38C41261EB4E0680042957D /* CPUTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CPUTime.cpp; sourceTree = "<group>"; };
                E38C41271EB4E0680042957D /* CPUTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CPUTime.h; sourceTree = "<group>"; };
                                0F3501631BB258C800F0A2A3 /* WeakRandom.h */,
                                0FE4479A1B7AAA03009498EB /* WordLock.cpp */,
                                0FE4479B1B7AAA03009498EB /* WordLock.h */,
+                               E388886D20C9095100E632BC /* WorkerPool.cpp */,
+                               E388886E20C9095100E632BC /* WorkerPool.h */,
                                E4A0AD371A96245500536DF6 /* WorkQueue.cpp */,
                                E4A0AD381A96245500536DF6 /* WorkQueue.h */,
                                FE05FAFE1FE5007500093230 /* WTFAssertions.cpp */,
                                0F66B2921DC97BAB004A1D3F /* WallTime.cpp in Sources */,
                                1FA47C8A152502DA00568D1B /* WebCoreThread.cpp in Sources */,
                                0FE4479C1B7AAA03009498EB /* WordLock.cpp in Sources */,
+                               E388886F20C9095100E632BC /* WorkerPool.cpp in Sources */,
                                E4A0AD391A96245500536DF6 /* WorkQueue.cpp in Sources */,
                                E4A0AD3D1A96253C00536DF6 /* WorkQueueCocoa.cpp in Sources */,
                                FE05FAFF1FE5007500093230 /* WTFAssertions.cpp in Sources */,
index 2c486c4..a59c5d1 100644 (file)
@@ -104,9 +104,10 @@ bool AutomaticThreadCondition::contains(const AbstractLocker&, AutomaticThread*
     return m_threads.contains(thread);
 }
 
-AutomaticThread::AutomaticThread(const AbstractLocker& locker, Box<Lock> lock, RefPtr<AutomaticThreadCondition> condition)
+AutomaticThread::AutomaticThread(const AbstractLocker& locker, Box<Lock> lock, RefPtr<AutomaticThreadCondition> condition, Seconds timeout)
     : m_lock(lock)
     , m_condition(condition)
+    , m_timeout(timeout)
 {
     if (verbose)
         dataLog(RawPointer(this), ": Allocated AutomaticThread.\n");
@@ -204,10 +205,10 @@ void AutomaticThread::start(const AbstractLocker&)
                         // Shut the thread down after a timeout.
                         m_isWaiting = true;
                         bool awokenByNotify =
-                            m_waitCondition.waitFor(*m_lock, 10_s);
+                            m_waitCondition.waitFor(*m_lock, m_timeout);
                         if (verbose && !awokenByNotify && !m_isWaiting)
                             dataLog(RawPointer(this), ": waitFor timed out, but notified via m_isWaiting flag!\n");
-                        if (m_isWaiting) {
+                        if (m_isWaiting && shouldSleep(locker)) {
                             m_isWaiting = false;
                             if (verbose)
                                 dataLog(RawPointer(this), ": Going to sleep!\n");
index 1b90454..0054524 100644 (file)
@@ -129,7 +129,7 @@ public:
 protected:
     // This logically creates the thread, but in reality the thread won't be created until someone
     // calls AutomaticThreadCondition::notifyOne() or notifyAll().
-    AutomaticThread(const AbstractLocker&, Box<Lock>, RefPtr<AutomaticThreadCondition>);
+    AutomaticThread(const AbstractLocker&, Box<Lock>, RefPtr<AutomaticThreadCondition>, Seconds timeout = 10_s);
     
     // To understand PollResult and WorkResult, imagine that poll() and work() are being called like
     // so:
@@ -168,6 +168,11 @@ protected:
     // can be sure that the default ones don't do anything (so you don't need a super call).
     virtual void threadDidStart();
     virtual void threadIsStopping(const AbstractLocker&);
+
+    // Control whether this automatic thread should sleep when timeout happens.
+    // By overriding this function, we can customize how automatic threads will sleep.
+    // For example, when you have thread pool, you can decrease active threads moderately.
+    virtual bool shouldSleep(const AbstractLocker&) { return true; }
     
 private:
     friend class AutomaticThreadCondition;
@@ -176,6 +181,7 @@ private:
     
     Box<Lock> m_lock;
     RefPtr<AutomaticThreadCondition> m_condition;
+    Seconds m_timeout;
     bool m_isRunning { true };
     bool m_isWaiting { false };
     bool m_hasUnderlyingThread { false };
index 6ce617a..0f9f4e1 100644 (file)
@@ -256,6 +256,7 @@ set(WTF_PUBLIC_HEADERS
     WindowsExtras.h
     WordLock.h
     WorkQueue.h
+    WorkerPool.h
     dtoa.h
 
     dtoa/bignum-dtoa.h
@@ -390,6 +391,7 @@ set(WTF_SOURCES
     WallTime.cpp
     WordLock.cpp
     WorkQueue.cpp
+    WorkerPool.cpp
     dtoa.cpp
 
     dtoa/bignum-dtoa.cc
diff --git a/Source/WTF/wtf/WorkerPool.cpp b/Source/WTF/wtf/WorkerPool.cpp
new file mode 100644 (file)
index 0000000..b879076
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WorkerPool.h"
+
+#include <wtf/NeverDestroyed.h>
+
+namespace WTF {
+
+class WorkerPool::Worker final : public AutomaticThread {
+public:
+    friend class WorkerPool;
+
+    Worker(const AbstractLocker& locker, WorkerPool& pool, Box<Lock> lock, RefPtr<AutomaticThreadCondition> condition, Seconds timeout)
+        : AutomaticThread(locker, lock, condition, timeout)
+        , m_pool(pool)
+    {
+    }
+
+    PollResult poll(const AbstractLocker&) final
+    {
+        if (m_pool.m_tasks.isEmpty())
+            return PollResult::Wait;
+        m_task = m_pool.m_tasks.takeFirst();
+        if (!m_task)
+            return PollResult::Stop;
+        return PollResult::Work;
+    }
+
+    WorkResult work() final
+    {
+        m_task();
+        m_task = nullptr;
+        return WorkResult::Continue;
+    }
+
+    void threadDidStart() final
+    {
+        LockHolder locker(*m_pool.m_lock);
+        m_pool.m_numberOfActiveWorkers++;
+    }
+
+    void threadIsStopping(const AbstractLocker&) final
+    {
+        m_pool.m_numberOfActiveWorkers--;
+    }
+
+    bool shouldSleep(const AbstractLocker& locker) final
+    {
+        return m_pool.shouldSleep(locker);
+    }
+
+private:
+    WorkerPool& m_pool;
+    Function<void()> m_task;
+};
+
+WorkerPool::WorkerPool(unsigned numberOfWorkers, Seconds timeout)
+    : m_lock(Box<Lock>::create())
+    , m_condition(AutomaticThreadCondition::create())
+    , m_timeout(timeout)
+{
+    LockHolder locker(*m_lock);
+    for (unsigned i = 0; i < numberOfWorkers; ++i)
+        m_workers.append(adoptRef(*new Worker(locker, *this, m_lock, m_condition, timeout)));
+}
+
+WorkerPool::~WorkerPool()
+{
+    {
+        LockHolder locker(*m_lock);
+        for (unsigned i = m_workers.size(); i--;)
+            m_tasks.append(nullptr); // Use null task to indicate that we want the thread to terminate.
+        m_condition->notifyAll(locker);
+    }
+    for (auto& worker : m_workers)
+        worker->join();
+    ASSERT(!m_numberOfActiveWorkers);
+}
+
+bool WorkerPool::shouldSleep(const AbstractLocker&)
+{
+    if (m_timeout > 0_s && std::isinf(m_timeout))
+        return false;
+
+    MonotonicTime currentTime = MonotonicTime::now();
+    if (std::isnan(m_lastTimeoutTime) || (currentTime >= (m_lastTimeoutTime  + m_timeout))) {
+        m_lastTimeoutTime = currentTime;
+        return true;
+    }
+    return false;
+}
+
+void WorkerPool::postTask(Function<void()>&& task)
+{
+    LockHolder locker(*m_lock);
+    m_tasks.append(WTFMove(task));
+    m_condition->notifyOne(locker);
+}
+
+}
diff --git a/Source/WTF/wtf/WorkerPool.h b/Source/WTF/wtf/WorkerPool.h
new file mode 100644 (file)
index 0000000..b5f4d34
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/AutomaticThread.h>
+#include <wtf/Deque.h>
+#include <wtf/Function.h>
+#include <wtf/NumberOfCores.h>
+#include <wtf/Vector.h>
+
+namespace WTF {
+
+class WorkerPool : public ThreadSafeRefCounted<WorkerPool> {
+public:
+    WTF_EXPORT_PRIVATE void postTask(Function<void()>&&);
+
+    WTF_EXPORT_PRIVATE ~WorkerPool();
+
+    // If timeout is infinity, it means AutomaticThread will be never automatically destroyed.
+    static Ref<WorkerPool> create(unsigned numberOfWorkers  = WTF::numberOfProcessorCores(), Seconds timeout = Seconds::infinity())
+    {
+        ASSERT(numberOfWorkers >= 1);
+        return adoptRef(*new WorkerPool(numberOfWorkers, timeout));
+    }
+
+private:
+    class Worker;
+    friend class Worker;
+
+    WTF_EXPORT_PRIVATE WorkerPool(unsigned numberOfWorkers, Seconds timeout);
+
+    bool shouldSleep(const AbstractLocker&);
+
+    Box<Lock> m_lock;
+    RefPtr<AutomaticThreadCondition> m_condition;
+    Seconds m_timeout;
+    MonotonicTime m_lastTimeoutTime { MonotonicTime::nan() };
+    unsigned m_numberOfActiveWorkers { 0 };
+    Vector<Ref<Worker>> m_workers;
+    Deque<Function<void()>> m_tasks;
+};
+
+}
+
+using WTF::WorkerPool;
index 1afd09e..4df30a9 100644 (file)
@@ -1,3 +1,20 @@
+2018-06-07  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [WTF] Add WorkerPool
+        https://bugs.webkit.org/show_bug.cgi?id=174569
+
+        Reviewed by Carlos Garcia Campos.
+
+        We start using WorkerPool for NicosiaPaintingEngineThreaded instead of glib thread pool.
+        This makes NicosiaPaintingEngineThreaded platform-independent and usable for WinCairo.
+
+        * platform/graphics/nicosia/NicosiaPaintingEngineThreaded.cpp:
+        (Nicosia::PaintingEngineThreaded::PaintingEngineThreaded):
+        (Nicosia::PaintingEngineThreaded::~PaintingEngineThreaded):
+        (Nicosia::PaintingEngineThreaded::paint):
+        (Nicosia::s_threadFunc): Deleted.
+        * platform/graphics/nicosia/NicosiaPaintingEngineThreaded.h:
+
 2018-06-08  Miguel Gomez  <magomez@igalia.com>
 
         [GTK][WPE] Wrong result when calling ImageBufferCairo's getImageData()
index b72895c..760878b 100644 (file)
 #include "GraphicsLayer.h"
 #include "NicosiaBuffer.h"
 #include "NicosiaPaintingContext.h"
-#include <glib.h>
-#include <wtf/FastMalloc.h>
 
 namespace Nicosia {
 using namespace WebCore;
 
-struct TaskData {
-    WTF_MAKE_STRUCT_FAST_ALLOCATED;
-
-    Ref<Buffer> buffer;
-    PaintingOperations paintingOperations;
-};
-
-void s_threadFunc(gpointer data, gpointer)
-{
-    std::unique_ptr<TaskData> taskData(static_cast<TaskData*>(data));
-
-    PaintingContext::replay(taskData->buffer, taskData->paintingOperations);
-    taskData->buffer->completePainting();
-}
-
 static void paintLayer(GraphicsContext& context, GraphicsLayer& layer, const IntRect& sourceRect, const IntRect& mappedSourceRect, const IntRect& targetRect, float contentsScale, bool supportsAlpha)
 {
     context.save();
@@ -77,14 +60,12 @@ static void paintLayer(GraphicsContext& context, GraphicsLayer& layer, const Int
 }
 
 PaintingEngineThreaded::PaintingEngineThreaded()
+    : m_workerPool(WorkerPool::create(4))
 {
-    // FIXME: these parameters should be fine-tuned, or maybe made configurable.
-    m_threadPool = g_thread_pool_new(s_threadFunc, nullptr, 4, TRUE, nullptr);
 }
 
 PaintingEngineThreaded::~PaintingEngineThreaded()
 {
-    g_thread_pool_free(m_threadPool, TRUE, FALSE);
 }
 
 bool PaintingEngineThreaded::paint(GraphicsLayer& layer, Ref<Buffer>&& buffer, const IntRect& sourceRect, const IntRect& mappedSourceRect, const IntRect& targetRect, float contentsScale)
@@ -98,7 +79,10 @@ bool PaintingEngineThreaded::paint(GraphicsLayer& layer, Ref<Buffer>&& buffer, c
             paintLayer(context, layer, sourceRect, mappedSourceRect, targetRect, contentsScale, buffer->supportsAlpha());
         });
 
-    g_thread_pool_push(m_threadPool, new TaskData { WTFMove(buffer), WTFMove(paintingOperations) }, nullptr);
+    m_workerPool->postTask([paintingOperations = WTFMove(paintingOperations), buffer = WTFMove(buffer)] {
+        PaintingContext::replay(buffer, paintingOperations);
+        buffer->completePainting();
+    });
 
     return true;
 }
index 2f1ff80..f5580bb 100644 (file)
@@ -31,8 +31,7 @@
 #if USE(COORDINATED_GRAPHICS_THREADED)
 
 #include "NicosiaPaintingEngine.h"
-
-typedef struct _GThreadPool GThreadPool;
+#include <wtf/WorkerPool.h>
 
 namespace Nicosia {
 
@@ -44,7 +43,7 @@ public:
 private:
     bool paint(WebCore::GraphicsLayer&, Ref<Buffer>&&, const WebCore::IntRect&, const WebCore::IntRect&, const WebCore::IntRect&, float) override;
 
-    GThreadPool* m_threadPool;
+    Ref<WorkerPool> m_workerPool;
 };
 
 } // namespace Nicosia
index 185b40a..b785bb2 100644 (file)
@@ -1,3 +1,15 @@
+2018-06-07  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [WTF] Add WorkerPool
+        https://bugs.webkit.org/show_bug.cgi?id=174569
+
+        Reviewed by Carlos Garcia Campos.
+
+        * TestWebKitAPI/CMakeLists.txt:
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WTF/WorkerPool.cpp: Added.
+        (TestWebKitAPI::TEST):
+
 2018-06-07  Fujii Hironori  <Hironori.Fujii@sony.com>
 
         [Win][MiniBrowser] Add a new BrowserWindow interface to abstract WK1 and WK2 BrowserWindow
index 10f8fca..2e7d1c3 100644 (file)
@@ -158,6 +158,7 @@ set(TestWTF_SOURCES
     ${TESTWEBKITAPI_DIR}/Tests/WTF/WTFString.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/WeakPtr.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/WorkQueue.cpp
+    ${TESTWEBKITAPI_DIR}/Tests/WTF/WorkerPool.cpp
 )
 
 # FIXME: Tests/WTF/RunLoop.cpp is missing because it doesn't work for Windows.
index 590720d..d658305 100644 (file)
                E194E1BA177E5145009C4D4E /* StopLoadingFromDidReceiveResponse.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = StopLoadingFromDidReceiveResponse.mm; sourceTree = "<group>"; };
                E194E1BC177E534A009C4D4E /* StopLoadingFromDidReceiveResponse.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = StopLoadingFromDidReceiveResponse.html; sourceTree = "<group>"; };
                E19DB9781B32137C00DB38D4 /* NavigatorLanguage.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NavigatorLanguage.mm; sourceTree = "<group>"; };
+               E388887020C9098100E632BC /* WorkerPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WorkerPool.cpp; sourceTree = "<group>"; };
                E38A0D341FD50CBC00E98C8B /* Threading.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Threading.cpp; sourceTree = "<group>"; };
                E3953F951F2CF32100A76A2E /* Signals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Signals.cpp; sourceTree = "<group>"; };
                E398BC0F2041C76300387136 /* UniqueArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UniqueArray.cpp; sourceTree = "<group>"; };
                                7CD0D5AA1D5534DE000CC9E1 /* Variant.cpp */,
                                BC55F5F814AD78EE00484BE1 /* Vector.cpp */,
                                1CB9BC371A67482300FE5678 /* WeakPtr.cpp */,
+                               E388887020C9098100E632BC /* WorkerPool.cpp */,
                                7AA6A1511AAC0B31002B2ED3 /* WorkQueue.cpp */,
                                265AF54F15D1E48A00B0CB4A /* WTFString.cpp */,
                        );
diff --git a/Tools/TestWebKitAPI/Tests/WTF/WorkerPool.cpp b/Tools/TestWebKitAPI/Tests/WTF/WorkerPool.cpp
new file mode 100644 (file)
index 0000000..f98e28a
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <wtf/DataLog.h>
+#include <wtf/Seconds.h>
+#include <wtf/Threading.h>
+#include <wtf/WorkerPool.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF, WorkerPoolDecrease)
+{
+    std::atomic<unsigned> counter { 0 };
+    {
+        Ref<WorkerPool> pool = WorkerPool::create();
+        for (int i = 0; i < 10000; ++i) {
+            pool->postTask([&] {
+                ++counter;
+                Thread::yield();
+            });
+        }
+        // When destroying WorkerPool, all the tasks are drained.
+    }
+    EXPECT_EQ(counter.load(), 10000U);
+}
+
+} // namespace TestWebKitAPI