summaryrefslogtreecommitdiff
path: root/Source/WTF
diff options
context:
space:
mode:
authorKonstantin Tokarev <annulen@yandex.ru>2017-03-30 15:27:58 +0300
committerKonstantin Tokarev <annulen@yandex.ru>2017-03-31 10:31:00 +0000
commitbe770ca621f6463339b7d15be088e1b9acd851e5 (patch)
tree1a843019f693c100adea3f3acd47999f3eba2796 /Source/WTF
parenteaaf1391d58f17bde794d6c8634e092209898941 (diff)
downloadqtwebkit-be770ca621f6463339b7d15be088e1b9acd851e5.tar.gz
Import WebKit commit 13ac532967b6ac2d18d6fc4ea72c4ca35eccff20
Change-Id: I12a5c8f98aeaac1b542ce20c0ff297c57b5d84d1 Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/WTF')
-rw-r--r--Source/WTF/wtf/PlatformQt.cmake14
-rw-r--r--Source/WTF/wtf/WorkQueue.cpp2
-rw-r--r--Source/WTF/wtf/WorkQueue.h13
-rw-r--r--Source/WTF/wtf/cocoa/WorkQueueCocoa.cpp112
-rw-r--r--Source/WTF/wtf/threads/BinarySemaphore.h8
-rw-r--r--Source/WTF/wtf/threads/win/BinarySemaphoreWin.cpp75
-rw-r--r--Source/WTF/wtf/win/MainThreadWin.cpp76
-rw-r--r--Source/WTF/wtf/win/RunLoopWin.cpp176
-rw-r--r--Source/WTF/wtf/win/WTFDLL.cpp50
-rw-r--r--Source/WTF/wtf/win/WorkItemWin.cpp68
-rw-r--r--Source/WTF/wtf/win/WorkItemWin.h72
-rw-r--r--Source/WTF/wtf/win/WorkQueueWin.cpp281
12 files changed, 940 insertions, 7 deletions
diff --git a/Source/WTF/wtf/PlatformQt.cmake b/Source/WTF/wtf/PlatformQt.cmake
index 7efcd4015..636ad40c2 100644
--- a/Source/WTF/wtf/PlatformQt.cmake
+++ b/Source/WTF/wtf/PlatformQt.cmake
@@ -1,7 +1,6 @@
list(APPEND WTF_SOURCES
qt/MainThreadQt.cpp
qt/RunLoopQt.cpp
- qt/WorkQueueQt.cpp
text/qt/StringQt.cpp
)
@@ -30,6 +29,8 @@ endif ()
if (UNIX AND NOT APPLE)
list(APPEND WTF_SOURCES
UniStdExtras.cpp
+
+ qt/WorkQueueQt.cpp
)
endif ()
@@ -47,6 +48,15 @@ if (USE_GLIB)
endif ()
if (WIN32)
+ list(REMOVE_ITEM WTF_SOURCES
+ threads/BinarySemaphore.cpp
+ )
+ list(APPEND WTF_SOURCES
+ threads/win/BinarySemaphoreWin.cpp
+
+ win/WorkItemWin.cpp
+ win/WorkQueueWin.cpp
+ )
list(APPEND WTF_LIBRARIES
winmm
)
@@ -54,6 +64,8 @@ endif ()
if (APPLE)
list(APPEND WTF_SOURCES
+ cocoa/WorkQueueCocoa.cpp
+
text/cf/AtomicStringImplCF.cpp
text/cf/StringCF.cpp
text/cf/StringImplCF.cpp
diff --git a/Source/WTF/wtf/WorkQueue.cpp b/Source/WTF/wtf/WorkQueue.cpp
index 43b6450b2..e26ae3bf2 100644
--- a/Source/WTF/wtf/WorkQueue.cpp
+++ b/Source/WTF/wtf/WorkQueue.cpp
@@ -52,7 +52,7 @@ WorkQueue::~WorkQueue()
platformInvalidate();
}
-#if !PLATFORM(COCOA)
+#if !PLATFORM(COCOA) && !(PLATFORM(QT) && OS(DARWIN))
void WorkQueue::concurrentApply(size_t iterations, const std::function<void (size_t index)>& function)
{
if (!iterations)
diff --git a/Source/WTF/wtf/WorkQueue.h b/Source/WTF/wtf/WorkQueue.h
index ca93aa7f8..97e52897e 100644
--- a/Source/WTF/wtf/WorkQueue.h
+++ b/Source/WTF/wtf/WorkQueue.h
@@ -44,7 +44,7 @@
#include <wtf/glib/GRefPtr.h>
#elif PLATFORM(EFL)
#include <DispatchQueueEfl.h>
-#elif PLATFORM(QT)
+#elif PLATFORM(QT) && USE(UNIX_DOMAIN_SOCKETS)
#include <QSocketNotifier>
#elif OS(WINDOWS)
#include <wtf/HashMap.h>
@@ -52,7 +52,7 @@
#include <wtf/win/WorkItemWin.h>
#endif
-#if PLATFORM(QT)
+#if PLATFORM(QT) && USE(UNIX_DOMAIN_SOCKETS)
QT_BEGIN_NAMESPACE
class QProcess;
QT_END_NAMESPACE
@@ -87,9 +87,12 @@ public:
#elif PLATFORM(EFL)
void registerSocketEventHandler(int, std::function<void ()>);
void unregisterSocketEventHandler(int);
-#elif PLATFORM(QT)
+#elif PLATFORM(QT) && USE(UNIX_DOMAIN_SOCKETS)
QSocketNotifier* registerSocketEventHandler(int, QSocketNotifier::Type, std::function<void()>);
void dispatchOnTermination(QProcess*, std::function<void()>);
+#elif PLATFORM(QT) && OS(WINDOWS)
+ void registerHandle(HANDLE, const std::function<void()>&);
+ void unregisterAndCloseHandle(HANDLE);
#elif OS(DARWIN)
dispatch_queue_t dispatchQueue() const { return m_dispatchQueue; }
#endif
@@ -100,7 +103,7 @@ private:
void platformInitialize(const char* name, Type, QOS);
void platformInvalidate();
-#if PLATFORM(WIN)
+#if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS))
static void CALLBACK handleCallback(void* context, BOOLEAN timerOrWaitFired);
static void CALLBACK timerCallback(void* context, BOOLEAN timerOrWaitFired);
static DWORD WINAPI workThreadCallback(void* context);
@@ -122,7 +125,7 @@ private:
Condition m_terminateRunLoopCondition;
#elif PLATFORM(EFL)
RefPtr<DispatchQueue> m_dispatchQueue;
-#elif PLATFORM(QT)
+#elif PLATFORM(QT) && USE(UNIX_DOMAIN_SOCKETS)
class WorkItemQt;
QThread* m_workThread;
friend class WorkItemQt;
diff --git a/Source/WTF/wtf/cocoa/WorkQueueCocoa.cpp b/Source/WTF/wtf/cocoa/WorkQueueCocoa.cpp
new file mode 100644
index 000000000..134961ec7
--- /dev/null
+++ b/Source/WTF/wtf/cocoa/WorkQueueCocoa.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * 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 "WorkQueue.h"
+
+namespace WTF {
+
+void WorkQueue::dispatch(std::function<void ()> function)
+{
+ ref();
+ dispatch_async(m_dispatchQueue, ^{
+ function();
+ deref();
+ });
+}
+
+void WorkQueue::dispatchAfter(std::chrono::nanoseconds duration, std::function<void ()> function)
+{
+ ref();
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, duration.count()), m_dispatchQueue, ^{
+ function();
+ deref();
+ });
+}
+
+#if HAVE(QOS_CLASSES)
+static dispatch_qos_class_t dispatchQOSClass(WorkQueue::QOS qos)
+{
+ switch (qos) {
+ case WorkQueue::QOS::UserInteractive:
+ return QOS_CLASS_USER_INTERACTIVE;
+ case WorkQueue::QOS::UserInitiated:
+ return QOS_CLASS_USER_INITIATED;
+ case WorkQueue::QOS::Default:
+ return QOS_CLASS_DEFAULT;
+ case WorkQueue::QOS::Utility:
+ return QOS_CLASS_UTILITY;
+ case WorkQueue::QOS::Background:
+ return QOS_CLASS_BACKGROUND;
+ }
+}
+#else
+static dispatch_queue_t targetQueueForQOSClass(WorkQueue::QOS qos)
+{
+ switch (qos) {
+ case WorkQueue::QOS::UserInteractive:
+ case WorkQueue::QOS::UserInitiated:
+ return dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
+ case WorkQueue::QOS::Utility:
+ return dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
+ case WorkQueue::QOS::Background:
+ return dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
+ case WorkQueue::QOS::Default:
+ ASSERT_NOT_REACHED();
+ return nullptr;
+ }
+ ASSERT_NOT_REACHED();
+}
+#endif
+
+void WorkQueue::platformInitialize(const char* name, Type type, QOS qos)
+{
+ dispatch_queue_attr_t attr = type == Type::Concurrent ? DISPATCH_QUEUE_CONCURRENT : DISPATCH_QUEUE_SERIAL;
+#if HAVE(QOS_CLASSES)
+ attr = dispatch_queue_attr_make_with_qos_class(attr, dispatchQOSClass(qos), 0);
+#else
+ UNUSED_PARAM(qos);
+#endif
+ m_dispatchQueue = dispatch_queue_create(name, attr);
+#if !HAVE(QOS_CLASSES)
+ if (qos != WorkQueue::QOS::Default)
+ dispatch_set_target_queue(m_dispatchQueue, targetQueueForQOSClass(qos));
+#endif
+ dispatch_set_context(m_dispatchQueue, this);
+}
+
+void WorkQueue::platformInvalidate()
+{
+ dispatch_release(m_dispatchQueue);
+}
+
+void WorkQueue::concurrentApply(size_t iterations, const std::function<void (size_t index)>& function)
+{
+ dispatch_apply(iterations, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index) {
+ function(index);
+ });
+}
+
+}
diff --git a/Source/WTF/wtf/threads/BinarySemaphore.h b/Source/WTF/wtf/threads/BinarySemaphore.h
index b5db5d7ad..9585dc978 100644
--- a/Source/WTF/wtf/threads/BinarySemaphore.h
+++ b/Source/WTF/wtf/threads/BinarySemaphore.h
@@ -41,11 +41,19 @@ public:
WTF_EXPORT_PRIVATE void signal();
WTF_EXPORT_PRIVATE bool wait(double absoluteTime);
+#if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS))
+ HANDLE event() const { return m_event; }
+#endif
+
private:
+#if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS))
+ HANDLE m_event;
+#else
bool m_isSet;
Mutex m_mutex;
ThreadCondition m_condition;
+#endif
};
} // namespace WTF
diff --git a/Source/WTF/wtf/threads/win/BinarySemaphoreWin.cpp b/Source/WTF/wtf/threads/win/BinarySemaphoreWin.cpp
new file mode 100644
index 000000000..0dad1ac5c
--- /dev/null
+++ b/Source/WTF/wtf/threads/win/BinarySemaphoreWin.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * 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 "BinarySemaphore.h"
+
+namespace WTF {
+
+BinarySemaphore::BinarySemaphore()
+ : m_event(::CreateEventW(0, FALSE, FALSE, 0))
+{
+}
+
+BinarySemaphore::~BinarySemaphore()
+{
+ ::CloseHandle(m_event);
+}
+
+void BinarySemaphore::signal()
+{
+ ::SetEvent(m_event);
+}
+
+bool BinarySemaphore::wait(double absoluteTime)
+{
+ DWORD interval = absoluteTimeToWaitTimeoutInterval(absoluteTime);
+ if (!interval) {
+ // Consider the wait to have timed out, even if the event has already been signaled, to
+ // match the WTF::ThreadCondition implementation.
+ return false;
+ }
+
+ DWORD result = ::WaitForSingleObject(m_event, interval);
+ switch (result) {
+ case WAIT_OBJECT_0:
+ // The event was signaled.
+ return true;
+
+ case WAIT_TIMEOUT:
+ // The wait timed out.
+ return false;
+
+ case WAIT_FAILED:
+ ASSERT_WITH_MESSAGE(false, "::WaitForSingleObject failed with error %lu", ::GetLastError());
+ return false;
+
+ default:
+ ASSERT_WITH_MESSAGE(false, "::WaitForSingleObject returned unexpected result %lu", result);
+ return false;
+ }
+}
+
+} // namespace WTF
diff --git a/Source/WTF/wtf/win/MainThreadWin.cpp b/Source/WTF/wtf/win/MainThreadWin.cpp
new file mode 100644
index 000000000..f324e8b61
--- /dev/null
+++ b/Source/WTF/wtf/win/MainThreadWin.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile Inc. All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 "MainThread.h"
+
+#include "Assertions.h"
+#include "Threading.h"
+#include "WindowsExtras.h"
+
+namespace WTF {
+
+static HWND threadingWindowHandle;
+static UINT threadingFiredMessage;
+const LPCWSTR kThreadingWindowClassName = L"ThreadingWindowClass";
+
+LRESULT CALLBACK ThreadingWindowWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ if (message == threadingFiredMessage)
+ dispatchFunctionsFromMainThread();
+ else
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ return 0;
+}
+
+void initializeMainThreadPlatform()
+{
+ if (threadingWindowHandle)
+ return;
+
+ WNDCLASSW wcex;
+ memset(&wcex, 0, sizeof(WNDCLASSW));
+ wcex.lpfnWndProc = ThreadingWindowWndProc;
+ wcex.lpszClassName = kThreadingWindowClassName;
+ RegisterClassW(&wcex);
+
+ threadingWindowHandle = CreateWindowW(kThreadingWindowClassName, 0, 0,
+ CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, HWND_MESSAGE, 0, 0, 0);
+ threadingFiredMessage = RegisterWindowMessageW(L"com.apple.WebKit.MainThreadFired");
+
+ initializeCurrentThreadInternal("Main Thread");
+}
+
+void scheduleDispatchFunctionsOnMainThread()
+{
+ ASSERT(threadingWindowHandle);
+ PostMessage(threadingWindowHandle, threadingFiredMessage, 0, 0);
+}
+
+} // namespace WTF
diff --git a/Source/WTF/wtf/win/RunLoopWin.cpp b/Source/WTF/wtf/win/RunLoopWin.cpp
new file mode 100644
index 000000000..4b45ad458
--- /dev/null
+++ b/Source/WTF/wtf/win/RunLoopWin.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * 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 "RunLoop.h"
+
+#include <wtf/CurrentTime.h>
+#include <wtf/WindowsExtras.h>
+
+namespace WTF {
+
+static const UINT PerformWorkMessage = WM_USER + 1;
+static const LPWSTR kRunLoopMessageWindowClassName = L"RunLoopMessageWindow";
+
+LRESULT CALLBACK RunLoop::RunLoopWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ if (RunLoop* runLoop = static_cast<RunLoop*>(getWindowPointer(hWnd, 0)))
+ return runLoop->wndProc(hWnd, message, wParam, lParam);
+
+ if (message == WM_CREATE) {
+ LPCREATESTRUCT createStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
+
+ // Associate the RunLoop with the window.
+ setWindowPointer(hWnd, 0, createStruct->lpCreateParams);
+ return 0;
+ }
+
+ return ::DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+LRESULT RunLoop::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message) {
+ case PerformWorkMessage:
+ performWork();
+ return 0;
+ case WM_TIMER:
+ RunLoop::TimerBase::timerFired(this, wParam);
+ return 0;
+ }
+
+ return ::DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+void RunLoop::run()
+{
+ MSG message;
+ while (BOOL result = ::GetMessage(&message, 0, 0, 0)) {
+ if (result == -1)
+ break;
+ ::TranslateMessage(&message);
+ ::DispatchMessage(&message);
+ }
+}
+
+void RunLoop::stop()
+{
+ ::PostQuitMessage(0);
+}
+
+bool RunLoop::registerRunLoopMessageWindowClass()
+{
+ // FIXME: This really only needs to be called once.
+
+ WNDCLASS windowClass = { 0 };
+ windowClass.lpfnWndProc = RunLoop::RunLoopWndProc;
+ windowClass.cbWndExtra = sizeof(RunLoop*);
+ windowClass.lpszClassName = kRunLoopMessageWindowClassName;
+
+ return !!::RegisterClass(&windowClass);
+}
+
+RunLoop::RunLoop()
+{
+ registerRunLoopMessageWindowClass();
+
+ m_runLoopMessageWindow = ::CreateWindow(kRunLoopMessageWindowClassName, 0, 0,
+ CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, HWND_MESSAGE, 0, 0, this);
+ ASSERT(::IsWindow(m_runLoopMessageWindow));
+}
+
+RunLoop::~RunLoop()
+{
+ // FIXME: Tear down the work item queue here.
+}
+
+void RunLoop::wakeUp()
+{
+ // FIXME: No need to wake up the run loop if we've already called dispatch
+ // before the run loop has had the time to respond.
+ ::PostMessage(m_runLoopMessageWindow, PerformWorkMessage, reinterpret_cast<WPARAM>(this), 0);
+}
+
+// RunLoop::Timer
+
+void RunLoop::TimerBase::timerFired(RunLoop* runLoop, uint64_t ID)
+{
+ TimerMap::iterator it = runLoop->m_activeTimers.find(ID);
+ if (it == runLoop->m_activeTimers.end()) {
+ // The timer must have been stopped after the WM_TIMER message was posted to the message queue.
+ return;
+ }
+
+ TimerBase* timer = it->value;
+
+ if (!timer->m_isRepeating) {
+ runLoop->m_activeTimers.remove(it);
+ ::KillTimer(runLoop->m_runLoopMessageWindow, ID);
+ }
+
+ timer->fired();
+}
+
+static uint64_t generateTimerID()
+{
+ static uint64_t uniqueTimerID = 1;
+ return uniqueTimerID++;
+}
+
+RunLoop::TimerBase::TimerBase(RunLoop& runLoop)
+ : m_runLoop(runLoop)
+ , m_ID(generateTimerID())
+ , m_isRepeating(false)
+{
+}
+
+RunLoop::TimerBase::~TimerBase()
+{
+ stop();
+}
+
+void RunLoop::TimerBase::start(double nextFireInterval, bool repeat)
+{
+ m_isRepeating = repeat;
+ m_runLoop.m_activeTimers.set(m_ID, this);
+ ::SetTimer(m_runLoop.m_runLoopMessageWindow, m_ID, nextFireInterval * 1000, 0);
+}
+
+void RunLoop::TimerBase::stop()
+{
+ TimerMap::iterator it = m_runLoop.m_activeTimers.find(m_ID);
+ if (it == m_runLoop.m_activeTimers.end())
+ return;
+
+ m_runLoop.m_activeTimers.remove(it);
+ ::KillTimer(m_runLoop.m_runLoopMessageWindow, m_ID);
+}
+
+bool RunLoop::TimerBase::isActive() const
+{
+ return m_runLoop.m_activeTimers.contains(m_ID);
+}
+
+} // namespace WTF
diff --git a/Source/WTF/wtf/win/WTFDLL.cpp b/Source/WTF/wtf/win/WTFDLL.cpp
new file mode 100644
index 000000000..779e1b862
--- /dev/null
+++ b/Source/WTF/wtf/win/WTFDLL.cpp
@@ -0,0 +1,50 @@
+/*
+* Copyright (C) 2015 Apple Inc. All rights reserved.
+*
+* 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 <Windows.h>
+#include <math.h>
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ switch (fdwReason) {
+ case DLL_PROCESS_ATTACH:
+#if defined(_M_X64) || defined(__x86_64__)
+ // The VS2013 runtime has a bug where it mis-detects AVX-capable processors
+ // if the feature has been disabled in firmware. This causes us to crash
+ // in some of the math functions. For now, we disable those optimizations
+ // because Microsoft is not going to fix the problem in VS2013.
+ // FIXME: http://webkit.org/b/141449: Remove this workaround when we switch to VS2015+.
+ _set_FMA3_enable(0);
+#endif
+ break;
+
+ case DLL_PROCESS_DETACH:
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/Source/WTF/wtf/win/WorkItemWin.cpp b/Source/WTF/wtf/win/WorkItemWin.cpp
new file mode 100644
index 000000000..33ddf8ed9
--- /dev/null
+++ b/Source/WTF/wtf/win/WorkItemWin.cpp
@@ -0,0 +1,68 @@
+/*
+* Copyright (C) 2010, 2015 Apple Inc. All rights reserved.
+*
+* 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 "WorkItemWin.h"
+
+#include <Windows.h>
+#include <wtf/Threading.h>
+#include <wtf/WorkQueue.h>
+
+namespace WTF {
+
+WorkItemWin::WorkItemWin(std::function<void()> function, WorkQueue* queue)
+ : m_function(function)
+ , m_queue(queue)
+{
+}
+
+RefPtr<WorkItemWin> WorkItemWin::create(std::function<void()> function, WorkQueue* queue)
+{
+ return adoptRef(new WorkItemWin(function, queue));
+}
+
+WorkItemWin::~WorkItemWin()
+{
+}
+
+HandleWorkItem::HandleWorkItem(HANDLE handle, const std::function<void()>& function, WorkQueue* queue)
+ : WorkItemWin(function, queue)
+ , m_handle(handle)
+ , m_waitHandle(0)
+{
+ ASSERT_ARG(handle, handle);
+}
+
+RefPtr<HandleWorkItem> HandleWorkItem::createByAdoptingHandle(HANDLE handle, const std::function<void()>& function, WorkQueue* queue)
+{
+ return adoptRef(new HandleWorkItem(handle, function, queue));
+}
+
+HandleWorkItem::~HandleWorkItem()
+{
+ ::CloseHandle(m_handle);
+}
+
+} // namespace WTF
diff --git a/Source/WTF/wtf/win/WorkItemWin.h b/Source/WTF/wtf/win/WorkItemWin.h
new file mode 100644
index 000000000..af3fa1799
--- /dev/null
+++ b/Source/WTF/wtf/win/WorkItemWin.h
@@ -0,0 +1,72 @@
+/*
+* Copyright (C) 2010, 2015 Apple Inc. All rights reserved.
+* Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved.
+*
+* 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.
+*/
+
+#ifndef WorkItemWin_h
+#define WorkItemWin_h
+
+#include <Windows.h>
+#include <functional>
+#include <wtf/RefPtr.h>
+#include <wtf/ThreadSafeRefCounted.h>
+
+namespace WTF {
+
+class WorkQueue;
+
+class WorkItemWin : public ThreadSafeRefCounted<WorkItemWin> {
+public:
+ static RefPtr<WorkItemWin> create(std::function<void()>, WorkQueue*);
+ virtual ~WorkItemWin();
+
+ std::function<void()>& function() { return m_function; }
+ WorkQueue* queue() const { return m_queue.get(); }
+
+protected:
+ WorkItemWin(std::function<void()>, WorkQueue*);
+
+private:
+ std::function<void()> m_function;
+ RefPtr<WorkQueue> m_queue;
+};
+
+class HandleWorkItem : public WorkItemWin {
+public:
+ static RefPtr<HandleWorkItem> createByAdoptingHandle(HANDLE, const std::function<void()>&, WorkQueue*);
+ virtual ~HandleWorkItem();
+
+ void setWaitHandle(HANDLE waitHandle) { m_waitHandle = waitHandle; }
+ HANDLE waitHandle() const { return m_waitHandle; }
+
+private:
+ HandleWorkItem(HANDLE, const std::function<void()>&, WorkQueue*);
+
+ HANDLE m_handle;
+ HANDLE m_waitHandle;
+};
+
+}
+
+#endif
diff --git a/Source/WTF/wtf/win/WorkQueueWin.cpp b/Source/WTF/wtf/win/WorkQueueWin.cpp
new file mode 100644
index 000000000..6e61cde69
--- /dev/null
+++ b/Source/WTF/wtf/win/WorkQueueWin.cpp
@@ -0,0 +1,281 @@
+/*
+* Copyright (C) 2010, 2015 Apple Inc. All rights reserved.
+*
+* 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 "WorkQueue.h"
+
+#include <wtf/MathExtras.h>
+#include <wtf/Threading.h>
+#include <wtf/win/WorkItemWin.h>
+
+namespace WTF {
+
+void WorkQueue::handleCallback(void* context, BOOLEAN timerOrWaitFired)
+{
+ ASSERT_ARG(context, context);
+ ASSERT_ARG(timerOrWaitFired, !timerOrWaitFired);
+
+ WorkItemWin* item = static_cast<WorkItemWin*>(context);
+ RefPtr<WorkQueue> queue = item->queue();
+
+ {
+ MutexLocker lock(queue->m_workItemQueueLock);
+ queue->m_workItemQueue.append(item);
+
+ // If no other thread is performing work, we can do it on this thread.
+ if (!queue->tryRegisterAsWorkThread()) {
+ // Some other thread is performing work. Since we hold the queue lock, we can be sure
+ // that the work thread is not exiting due to an empty queue and will process the work
+ // item we just added to it. If we weren't holding the lock we'd have to signal
+ // m_performWorkEvent to make sure the work item got picked up.
+ return;
+ }
+ }
+
+ queue->performWorkOnRegisteredWorkThread();
+}
+
+DWORD WorkQueue::workThreadCallback(void* context)
+{
+ ASSERT_ARG(context, context);
+
+ WorkQueue* queue = static_cast<WorkQueue*>(context);
+
+ if (!queue->tryRegisterAsWorkThread())
+ return 0;
+
+ queue->performWorkOnRegisteredWorkThread();
+ return 0;
+}
+
+void WorkQueue::performWorkOnRegisteredWorkThread()
+{
+ ASSERT(m_isWorkThreadRegistered);
+
+ m_workItemQueueLock.lock();
+
+ while (!m_workItemQueue.isEmpty()) {
+ Vector<RefPtr<WorkItemWin>> workItemQueue;
+ m_workItemQueue.swap(workItemQueue);
+
+ // Allow more work to be scheduled while we're not using the queue directly.
+ m_workItemQueueLock.unlock();
+ for (auto& workItem : workItemQueue) {
+ workItem->function()();
+ deref();
+ }
+ m_workItemQueueLock.lock();
+ }
+
+ // One invariant we maintain is that any work scheduled while a work thread is registered will
+ // be handled by that work thread. Unregister as the work thread while the queue lock is still
+ // held so that no work can be scheduled while we're still registered.
+ unregisterAsWorkThread();
+
+ m_workItemQueueLock.unlock();
+}
+
+void WorkQueue::platformInitialize(const char* name, Type, QOS)
+{
+ m_isWorkThreadRegistered = 0;
+ m_timerQueue = ::CreateTimerQueue();
+ ASSERT_WITH_MESSAGE(m_timerQueue, "::CreateTimerQueue failed with error %lu", ::GetLastError());
+}
+
+bool WorkQueue::tryRegisterAsWorkThread()
+{
+ LONG result = ::InterlockedCompareExchange(&m_isWorkThreadRegistered, 1, 0);
+ ASSERT(!result || result == 1);
+ return !result;
+}
+
+void WorkQueue::unregisterAsWorkThread()
+{
+ LONG result = ::InterlockedCompareExchange(&m_isWorkThreadRegistered, 0, 1);
+ ASSERT_UNUSED(result, result == 1);
+}
+
+void WorkQueue::platformInvalidate()
+{
+#if !ASSERT_DISABLED
+ MutexLocker lock(m_handlesLock);
+ ASSERT(m_handles.isEmpty());
+#endif
+
+ // FIXME: We need to ensure that any timer-queue timers that fire after this point don't try to
+ // access this WorkQueue <http://webkit.org/b/44690>.
+ ::DeleteTimerQueueEx(m_timerQueue, 0);
+}
+
+void WorkQueue::dispatch(std::function<void()> function)
+{
+ MutexLocker locker(m_workItemQueueLock);
+ ref();
+ m_workItemQueue.append(WorkItemWin::create(function, this));
+
+ // Spawn a work thread to perform the work we just added. As an optimization, we avoid
+ // spawning the thread if a work thread is already registered. This prevents multiple work
+ // threads from being spawned in most cases. (Note that when a work thread has been spawned but
+ // hasn't registered itself yet, m_isWorkThreadRegistered will be false and we'll end up
+ // spawning a second work thread here. But work thread registration process will ensure that
+ // only one thread actually ends up performing work.)
+ if (!m_isWorkThreadRegistered)
+ ::QueueUserWorkItem(workThreadCallback, this, WT_EXECUTEDEFAULT);
+}
+
+struct TimerContext : public ThreadSafeRefCounted<TimerContext> {
+ static RefPtr<TimerContext> create() { return adoptRef(new TimerContext); }
+
+ WorkQueue* queue;
+ std::function<void()> function;
+ Mutex timerMutex;
+ HANDLE timer;
+
+private:
+ TimerContext()
+ : queue(nullptr)
+ , timer(0)
+ {
+ }
+};
+
+void WorkQueue::timerCallback(void* context, BOOLEAN timerOrWaitFired)
+{
+ ASSERT_ARG(context, context);
+ ASSERT_UNUSED(timerOrWaitFired, timerOrWaitFired);
+
+ // Balanced by leakRef in scheduleWorkAfterDelay.
+ RefPtr<TimerContext> timerContext = adoptRef(static_cast<TimerContext*>(context));
+
+ timerContext->queue->dispatch(timerContext->function);
+
+ MutexLocker lock(timerContext->timerMutex);
+ ASSERT(timerContext->timer);
+ ASSERT(timerContext->queue->m_timerQueue);
+ if (!::DeleteTimerQueueTimer(timerContext->queue->m_timerQueue, timerContext->timer, 0)) {
+ // Getting ERROR_IO_PENDING here means that the timer will be destroyed once the callback is done executing.
+ ASSERT_WITH_MESSAGE(::GetLastError() == ERROR_IO_PENDING, "::DeleteTimerQueueTimer failed with error %lu", ::GetLastError());
+ }
+}
+
+void WorkQueue::dispatchAfter(std::chrono::nanoseconds duration, std::function<void()> function)
+{
+ ASSERT(m_timerQueue);
+ ref();
+
+ RefPtr<TimerContext> context = TimerContext::create();
+ context->queue = this;
+ context->function = function;
+
+ {
+ // The timer callback could fire before ::CreateTimerQueueTimer even returns, so we protect
+ // context->timer with a mutex to ensure the timer callback doesn't access it before the
+ // timer handle has been stored in it.
+ MutexLocker lock(context->timerMutex);
+
+ int64_t milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
+
+ // From empirical testing, we've seen CreateTimerQueueTimer() sometimes fire up to 5+ ms early.
+ // This causes havoc for clients of this code that expect to not be called back until the
+ // specified duration has expired. Other folks online have also observed some slop in the
+ // firing times of CreateTimerQuqueTimer(). From the data posted at
+ // http://omeg.pl/blog/2011/11/on-winapi-timers-and-their-resolution, it appears that the slop
+ // can be up to about 10 ms. To ensure that we don't fire the timer early, we'll tack on a
+ // slop adjustment to the duration, and we'll use double the worst amount of slop observed
+ // so far.
+ const int64_t slopAdjustment = 20;
+ if (milliseconds)
+ milliseconds += slopAdjustment;
+
+ // Since our timer callback is quick, we can execute in the timer thread itself and avoid
+ // an extra thread switch over to a worker thread.
+ if (!::CreateTimerQueueTimer(&context->timer, m_timerQueue, timerCallback, context.get(), clampTo<DWORD>(milliseconds), 0, WT_EXECUTEINTIMERTHREAD)) {
+ ASSERT_WITH_MESSAGE(false, "::CreateTimerQueueTimer failed with error %lu", ::GetLastError());
+ return;
+ }
+ }
+
+ // The timer callback will handle destroying context.
+ context.release().leakRef();
+}
+
+void WorkQueue::unregisterWaitAndDestroyItemSoon(PassRefPtr<HandleWorkItem> item)
+{
+ // We're going to make a blocking call to ::UnregisterWaitEx before closing the handle. (The
+ // blocking version of ::UnregisterWaitEx is much simpler than the non-blocking version.) If we
+ // do this on the current thread, we'll deadlock if we're currently in a callback function for
+ // the wait we're unregistering. So instead we do it asynchronously on some other worker thread.
+
+ ::QueueUserWorkItem(unregisterWaitAndDestroyItemCallback, item.leakRef(), WT_EXECUTEDEFAULT);
+}
+
+DWORD WINAPI WorkQueue::unregisterWaitAndDestroyItemCallback(void* context)
+{
+ ASSERT_ARG(context, context);
+ RefPtr<HandleWorkItem> item = adoptRef(static_cast<HandleWorkItem*>(context));
+
+ // Now that we know we're not in a callback function for the wait we're unregistering, we can
+ // make a blocking call to ::UnregisterWaitEx.
+ if (!::UnregisterWaitEx(item->waitHandle(), INVALID_HANDLE_VALUE)) {
+ DWORD error = ::GetLastError();
+ ASSERT_NOT_REACHED();
+ }
+
+ return 0;
+}
+
+#if PLATFORM(QT)
+void WorkQueue::registerHandle(HANDLE handle, const std::function<void()>& function)
+{
+ RefPtr<HandleWorkItem> handleItem = HandleWorkItem::createByAdoptingHandle(handle, function, this);
+
+ {
+ MutexLocker lock(m_handlesLock);
+ ASSERT_ARG(handle, !m_handles.contains(handle));
+ m_handles.set(handle, handleItem);
+ }
+
+ HANDLE waitHandle;
+ if (!::RegisterWaitForSingleObject(&waitHandle, handle, handleCallback, handleItem.get(), INFINITE, WT_EXECUTEDEFAULT)) {
+ DWORD error = ::GetLastError();
+ ASSERT_NOT_REACHED();
+ }
+ handleItem->setWaitHandle(waitHandle);
+}
+
+void WorkQueue::unregisterAndCloseHandle(HANDLE handle)
+{
+ RefPtr<HandleWorkItem> item;
+ {
+ MutexLocker locker(m_handlesLock);
+ ASSERT_ARG(handle, m_handles.contains(handle));
+ item = m_handles.take(handle);
+ }
+
+ unregisterWaitAndDestroyItemSoon(item.release());
+}
+#endif
+
+} // namespace WTF