<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[188907] releases/WebKitGTK/webkit-2.10</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/188907">188907</a></dd>
<dt>Author</dt> <dd>carlosgc@webkit.org</dd>
<dt>Date</dt> <dd>2015-08-25 05:40:25 -0700 (Tue, 25 Aug 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/188400">r188400</a> - WTF should have a compact Condition object to use with Lock
https://bugs.webkit.org/show_bug.cgi?id=147986

Reviewed by Geoffrey Garen.

Source/WTF:

Adds a condition variable implementation based on ParkingLot, called simply WTF::Condition.
It can be used with WTF::Lock or actually any lock implementation. It should even work with
WTF::SpinLock, WTF::Mutex, or std::mutex. Best of all, Condition only requires one byte.

ParkingLot almost contained all of the functionality needed to implemenet wait/notify. We
could have implemented Condition using a 32-bit (or even 64-bit) version that protects
against a notify that happens just before we park. But, this changes the ParkingLot API to
give us the ability to run some code between when ParkingLot enqueues the current thread
and when it actually sleeps. This callback is called with no locks held, so it can call
unlock() on any kind of lock, so long as that lock's unlock() method doesn't recurse into
ParkingLot::parkConditionally(). That seems unlikely; unlock() is more likely to call
ParkingLot::unparkOne() or unparkAll(). WTF::Lock will never call parkConditionally()
inside unlock(), so WTF::Lock is definitely appropriate for use with Condition.

Condition supports most of the API that std::condition_variable supports. It does some
things to try to reduce footgun potential. The preferred timeout form is waitUntil() which
takes an absolute time from the steady_clock. The only relative timeout form also takes a
predicate callback, so it's impossible to write the subtly incorrect
&quot;while (...) wait_for(...)&quot; idiom.

This patch doesn't actually introduce any uses of WTF::Condition other than the unit tests.
I'll start switching code over to using WTF::Condition in another patch.

* WTF.vcxproj/WTF.vcxproj:
* WTF.xcodeproj/project.pbxproj:
* wtf/CMakeLists.txt:
* wtf/Condition.h: Added.
(WTF::Condition::Condition):
(WTF::Condition::waitUntil):
(WTF::Condition::waitFor):
(WTF::Condition::wait):
(WTF::Condition::notifyOne):
(WTF::Condition::notifyAll):
* wtf/Lock.cpp:
(WTF::LockBase::unlockSlow): Make this useful assertion be a release assertion. It catches cases where you unlock the lock even though you don't hold it.
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionally): Add the beforeSleep() callback.
(WTF::ParkingLot::unparkOne):
* wtf/ParkingLot.h:
(WTF::ParkingLot::compareAndPark):

Tools:

Add a test for WTF::Condition.

* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.vcxproj/TestWebKitAPI.vcxproj:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp: Added.
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/Lock.cpp:
(TestWebKitAPI::runLockTest): Change the name of the thread.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit210SourceWTFChangeLog">releases/WebKitGTK/webkit-2.10/Source/WTF/ChangeLog</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceWTFWTFvcxprojWTFvcxproj">releases/WebKitGTK/webkit-2.10/Source/WTF/WTF.vcxproj/WTF.vcxproj</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceWTFWTFxcodeprojprojectpbxproj">releases/WebKitGTK/webkit-2.10/Source/WTF/WTF.xcodeproj/project.pbxproj</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceWTFwtfCMakeListstxt">releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/CMakeLists.txt</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceWTFwtfLockcpp">releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/Lock.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceWTFwtfParkingLotcpp">releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/ParkingLot.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceWTFwtfParkingLoth">releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/ParkingLot.h</a></li>
<li><a href="#releasesWebKitGTKwebkit210ToolsChangeLog">releases/WebKitGTK/webkit-2.10/Tools/ChangeLog</a></li>
<li><a href="#releasesWebKitGTKwebkit210ToolsTestWebKitAPICMakeListstxt">releases/WebKitGTK/webkit-2.10/Tools/TestWebKitAPI/CMakeLists.txt</a></li>
<li><a href="#releasesWebKitGTKwebkit210ToolsTestWebKitAPITestWebKitAPIvcxprojTestWebKitAPIvcxproj">releases/WebKitGTK/webkit-2.10/Tools/TestWebKitAPI/TestWebKitAPI.vcxproj/TestWebKitAPI.vcxproj</a></li>
<li><a href="#releasesWebKitGTKwebkit210ToolsTestWebKitAPITestWebKitAPIxcodeprojprojectpbxproj">releases/WebKitGTK/webkit-2.10/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj</a></li>
<li><a href="#releasesWebKitGTKwebkit210ToolsTestWebKitAPITestsWTFLockcpp">releases/WebKitGTK/webkit-2.10/Tools/TestWebKitAPI/Tests/WTF/Lock.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit210SourceWTFwtfConditionh">releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/Condition.h</a></li>
<li><a href="#releasesWebKitGTKwebkit210ToolsTestWebKitAPITestsWTFConditioncpp">releases/WebKitGTK/webkit-2.10/Tools/TestWebKitAPI/Tests/WTF/Condition.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="releasesWebKitGTKwebkit210SourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/WTF/ChangeLog (188906 => 188907)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/WTF/ChangeLog        2015-08-25 10:42:37 UTC (rev 188906)
+++ releases/WebKitGTK/webkit-2.10/Source/WTF/ChangeLog        2015-08-25 12:40:25 UTC (rev 188907)
</span><span class="lines">@@ -1,3 +1,51 @@
</span><ins>+2015-08-13  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        WTF should have a compact Condition object to use with Lock
+        https://bugs.webkit.org/show_bug.cgi?id=147986
+
+        Reviewed by Geoffrey Garen.
+
+        Adds a condition variable implementation based on ParkingLot, called simply WTF::Condition.
+        It can be used with WTF::Lock or actually any lock implementation. It should even work with
+        WTF::SpinLock, WTF::Mutex, or std::mutex. Best of all, Condition only requires one byte.
+
+        ParkingLot almost contained all of the functionality needed to implemenet wait/notify. We
+        could have implemented Condition using a 32-bit (or even 64-bit) version that protects
+        against a notify that happens just before we park. But, this changes the ParkingLot API to
+        give us the ability to run some code between when ParkingLot enqueues the current thread
+        and when it actually sleeps. This callback is called with no locks held, so it can call
+        unlock() on any kind of lock, so long as that lock's unlock() method doesn't recurse into
+        ParkingLot::parkConditionally(). That seems unlikely; unlock() is more likely to call
+        ParkingLot::unparkOne() or unparkAll(). WTF::Lock will never call parkConditionally()
+        inside unlock(), so WTF::Lock is definitely appropriate for use with Condition.
+
+        Condition supports most of the API that std::condition_variable supports. It does some
+        things to try to reduce footgun potential. The preferred timeout form is waitUntil() which
+        takes an absolute time from the steady_clock. The only relative timeout form also takes a
+        predicate callback, so it's impossible to write the subtly incorrect
+        &quot;while (...) wait_for(...)&quot; idiom.
+
+        This patch doesn't actually introduce any uses of WTF::Condition other than the unit tests.
+        I'll start switching code over to using WTF::Condition in another patch.
+
+        * WTF.vcxproj/WTF.vcxproj:
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/CMakeLists.txt:
+        * wtf/Condition.h: Added.
+        (WTF::Condition::Condition):
+        (WTF::Condition::waitUntil):
+        (WTF::Condition::waitFor):
+        (WTF::Condition::wait):
+        (WTF::Condition::notifyOne):
+        (WTF::Condition::notifyAll):
+        * wtf/Lock.cpp:
+        (WTF::LockBase::unlockSlow): Make this useful assertion be a release assertion. It catches cases where you unlock the lock even though you don't hold it.
+        * wtf/ParkingLot.cpp:
+        (WTF::ParkingLot::parkConditionally): Add the beforeSleep() callback.
+        (WTF::ParkingLot::unparkOne):
+        * wtf/ParkingLot.h:
+        (WTF::ParkingLot::compareAndPark):
+
</ins><span class="cx"> 2015-08-12  Anders Carlsson  &lt;andersca@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Use WTF::Optional in WindowFeatures
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceWTFWTFvcxprojWTFvcxproj"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/WTF/WTF.vcxproj/WTF.vcxproj (188906 => 188907)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/WTF/WTF.vcxproj/WTF.vcxproj        2015-08-25 10:42:37 UTC (rev 188906)
+++ releases/WebKitGTK/webkit-2.10/Source/WTF/WTF.vcxproj/WTF.vcxproj        2015-08-25 12:40:25 UTC (rev 188907)
</span><span class="lines">@@ -176,6 +176,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\CheckedArithmetic.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\CheckedBoolean.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\Compiler.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\wtf\Condition.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\CryptographicUtilities.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\CryptographicallyRandomNumber.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\CurrentTime.h&quot; /&gt;
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceWTFWTFxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/WTF/WTF.xcodeproj/project.pbxproj (188906 => 188907)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/WTF/WTF.xcodeproj/project.pbxproj        2015-08-25 10:42:37 UTC (rev 188906)
+++ releases/WebKitGTK/webkit-2.10/Source/WTF/WTF.xcodeproj/project.pbxproj        2015-08-25 12:40:25 UTC (rev 188907)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx">                 0FC4488316FE9FE100844BE9 /* ProcessID.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC4488216FE9FE100844BE9 /* ProcessID.h */; };
</span><span class="cx">                 0FC4EDE61696149600F65041 /* CommaPrinter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC4EDE51696149600F65041 /* CommaPrinter.h */; };
</span><span class="cx">                 0FD81AC5154FB22E00983E72 /* FastBitVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD81AC4154FB22E00983E72 /* FastBitVector.h */; settings = {ATTRIBUTES = (); }; };
</span><ins>+                0FDB698E1B7C643A000C1078 /* Condition.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDB698D1B7C643A000C1078 /* Condition.h */; };
</ins><span class="cx">                 0FDDBFA71666DFA300C55FEF /* StringPrintStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDDBFA51666DFA300C55FEF /* StringPrintStream.cpp */; };
</span><span class="cx">                 0FDDBFA81666DFA300C55FEF /* StringPrintStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDDBFA61666DFA300C55FEF /* StringPrintStream.h */; };
</span><span class="cx">                 0FE1646A1B6FFC9600400E7C /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE164681B6FFC9600400E7C /* Lock.cpp */; };
</span><span class="lines">@@ -327,6 +328,7 @@
</span><span class="cx">                 0FC4488216FE9FE100844BE9 /* ProcessID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessID.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FC4EDE51696149600F65041 /* CommaPrinter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommaPrinter.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FD81AC4154FB22E00983E72 /* FastBitVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FastBitVector.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0FDB698D1B7C643A000C1078 /* Condition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Condition.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0FDDBFA51666DFA300C55FEF /* StringPrintStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StringPrintStream.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FDDBFA61666DFA300C55FEF /* StringPrintStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringPrintStream.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FE164681B6FFC9600400E7C /* Lock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Lock.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -730,6 +732,7 @@
</span><span class="cx">                                 0F8F2B8F172E00F0007DBDA5 /* CompilationThread.cpp */,
</span><span class="cx">                                 0F8F2B90172E00F0007DBDA5 /* CompilationThread.h */,
</span><span class="cx">                                 A8A47270151A825A004123FF /* Compiler.h */,
</span><ins>+                                0FDB698D1B7C643A000C1078 /* Condition.h */,
</ins><span class="cx">                                 E15556F318A0CC18006F48FB /* CryptographicUtilities.cpp */,
</span><span class="cx">                                 E15556F418A0CC18006F48FB /* CryptographicUtilities.h */,
</span><span class="cx">                                 A8A47273151A825A004123FF /* CryptographicallyRandomNumber.cpp */,
</span><span class="lines">@@ -1185,6 +1188,7 @@
</span><span class="cx">                                 A8A47423151A825B004123FF /* SimpleStats.h in Headers */,
</span><span class="cx">                                 A8A47424151A825B004123FF /* SinglyLinkedList.h in Headers */,
</span><span class="cx">                                 A748745317A0BDAE00FA04CB /* SixCharacterHash.h in Headers */,
</span><ins>+                                0FDB698E1B7C643A000C1078 /* Condition.h in Headers */,
</ins><span class="cx">                                 A8A47426151A825B004123FF /* Spectrum.h in Headers */,
</span><span class="cx">                                 A8A47428151A825B004123FF /* StackBounds.h in Headers */,
</span><span class="cx">                                 FEDACD3E1630F83F00C69634 /* StackStats.h in Headers */,
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceWTFwtfCMakeListstxt"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/CMakeLists.txt (188906 => 188907)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/CMakeLists.txt        2015-08-25 10:42:37 UTC (rev 188906)
+++ releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/CMakeLists.txt        2015-08-25 12:40:25 UTC (rev 188907)
</span><span class="lines">@@ -10,6 +10,7 @@
</span><span class="cx">     ByteOrder.h
</span><span class="cx">     CompilationThread.h
</span><span class="cx">     Compiler.h
</span><ins>+    Condition.h
</ins><span class="cx">     CryptographicUtilities.h
</span><span class="cx">     CryptographicallyRandomNumber.h
</span><span class="cx">     CurrentTime.h
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceWTFwtfConditionh"></a>
<div class="addfile"><h4>Added: releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/Condition.h (0 => 188907)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/Condition.h                                (rev 0)
+++ releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/Condition.h        2015-08-25 12:40:25 UTC (rev 188907)
</span><span class="lines">@@ -0,0 +1,113 @@
</span><ins>+/*
+ * 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. 
+ */
+
+#ifndef WTF_Condition_h
+#define WTF_Condition_h
+
+#include &lt;chrono&gt;
+#include &lt;functional&gt;
+#include &lt;mutex&gt;
+#include &lt;wtf/ParkingLot.h&gt;
+
+namespace WTF {
+
+class Condition {
+public:
+    Condition() { }
+
+    // Wait on a parking queue while releasing the given lock. It will unlock the lock just before
+    // parking, and relock it upon wakeup. Returns true if we woke up due to some call to
+    // notifyOne() or notifyAll(). Returns false if we woke up due to a timeout.
+    template&lt;typename LockType&gt;
+    bool waitUntil(
+        LockType&amp; lock, std::chrono::steady_clock::time_point timeout)
+    {
+        bool result = ParkingLot::parkConditionally(
+            &amp;m_dummy,
+            [] () -&gt; bool { return true; },
+            [&amp;lock] () { lock.unlock(); },
+            timeout);
+        lock.lock();
+        return result;
+    }
+
+    // Wait until the given predicate is satisfied. Returns true if it is satisfied in the end.
+    // May return early due to timeout.
+    template&lt;typename LockType, typename Functor&gt;
+    bool waitUntil(
+        LockType&amp; lock, std::chrono::steady_clock::time_point timeout, const Functor&amp; predicate)
+    {
+        while (!predicate()) {
+            if (!waitUntil(lock, timeout))
+                return predicate();
+        }
+        return true;
+    }
+
+    // Wait until the given predicate is satisfied. Returns true if it is satisfied in the end.
+    // May return early due to timeout.
+    template&lt;typename LockType, typename DurationType, typename Functor&gt;
+    bool waitFor(
+        LockType&amp; lock, const DurationType&amp; relativeTimeout, const Functor&amp; predicate)
+    {
+        std::chrono::steady_clock::time_point absoluteTimeout =
+            std::chrono::steady_clock::now() +
+            std::chrono::duration_cast&lt;std::chrono::steady_clock::duration&gt;(relativeTimeout);
+
+        return waitUntil(lock, absoluteTimeout, predicate);
+    }
+
+    template&lt;typename LockType&gt;
+    void wait(LockType&amp; lock)
+    {
+        waitUntil(lock, std::chrono::steady_clock::time_point::max());
+    }
+
+    template&lt;typename LockType, typename Functor&gt;
+    void wait(LockType&amp; lock, const Functor&amp; predicate)
+    {
+        while (!predicate())
+            wait(lock);
+    }
+
+    void notifyOne()
+    {
+        ParkingLot::unparkOne(&amp;m_dummy);
+    }
+    
+    void notifyAll()
+    {
+        ParkingLot::unparkAll(&amp;m_dummy);
+    }
+    
+private:
+    
+    uint8_t m_dummy;
+};
+
+} // namespace WTF
+
+#endif // WTF_Condition_h
+
</ins></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceWTFwtfLockcpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/Lock.cpp (188906 => 188907)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/Lock.cpp        2015-08-25 10:42:37 UTC (rev 188906)
+++ releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/Lock.cpp        2015-08-25 12:40:25 UTC (rev 188907)
</span><span class="lines">@@ -81,7 +81,7 @@
</span><span class="cx">     // be held and parked if someone attempts to lock just as we are unlocking.
</span><span class="cx">     for (;;) {
</span><span class="cx">         uint8_t oldByteValue = m_byte.load();
</span><del>-        ASSERT(oldByteValue == isHeldBit || oldByteValue == (isHeldBit | hasParkedBit));
</del><ins>+        RELEASE_ASSERT(oldByteValue == isHeldBit || oldByteValue == (isHeldBit | hasParkedBit));
</ins><span class="cx">         
</span><span class="cx">         if (oldByteValue == isHeldBit) {
</span><span class="cx">             if (m_byte.compareExchangeWeak(isHeldBit, 0))
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceWTFwtfParkingLotcpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/ParkingLot.cpp (188906 => 188907)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/ParkingLot.cpp        2015-08-25 10:42:37 UTC (rev 188906)
+++ releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/ParkingLot.cpp        2015-08-25 12:40:25 UTC (rev 188907)
</span><span class="lines">@@ -507,13 +507,20 @@
</span><span class="cx"> 
</span><span class="cx"> } // anonymous namespace
</span><span class="cx"> 
</span><del>-bool ParkingLot::parkConditionally(const void* address, std::function&lt;bool()&gt; validation)
</del><ins>+bool ParkingLot::parkConditionally(
+    const void* address,
+    std::function&lt;bool()&gt; validation,
+    std::function&lt;void()&gt; beforeSleep,
+    std::chrono::steady_clock::time_point timeout)
</ins><span class="cx"> {
</span><span class="cx">     if (verbose)
</span><span class="cx">         dataLog(toString(currentThread(), &quot;: parking.\n&quot;));
</span><span class="cx">     
</span><span class="cx">     ThreadData* me = myThreadData();
</span><span class="cx"> 
</span><ins>+    // Guard against someone calling parkConditionally() recursively from beforeSleep().
+    RELEASE_ASSERT(!me-&gt;address);
+
</ins><span class="cx">     bool result = enqueue(
</span><span class="cx">         address,
</span><span class="cx">         [&amp;] () -&gt; ThreadData* {
</span><span class="lines">@@ -527,16 +534,49 @@
</span><span class="cx">     if (!result)
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><del>-    if (verbose)
-        dataLog(toString(currentThread(), &quot;: parking self: &quot;, RawPointer(me), &quot;\n&quot;));
</del><ins>+    beforeSleep();
+
+    bool didGetDequeued;
</ins><span class="cx">     {
</span><span class="cx">         std::unique_lock&lt;std::mutex&gt; locker(me-&gt;parkingLock);
</span><del>-        while (me-&gt;address)
-            me-&gt;parkingCondition.wait(locker);
</del><ins>+        while (me-&gt;address &amp;&amp; std::chrono::steady_clock::now() &lt; timeout)
+            me-&gt;parkingCondition.wait_until(locker, timeout);
+        ASSERT(!me-&gt;address || me-&gt;address == address);
+        didGetDequeued = !me-&gt;address;
</ins><span class="cx">     }
</span><del>-    if (verbose)
-        dataLog(toString(currentThread(), &quot;: unparked self: &quot;, RawPointer(me), &quot;\n&quot;));
-    return true;
</del><ins>+    if (didGetDequeued) {
+        // Great! We actually got dequeued rather than the timeout expiring.
+        return true;
+    }
+
+    // Have to remove ourselves from the queue since we timed out and nobody has dequeued us yet.
+
+    // It's possible that we get unparked right here, just before dequeue() grabs a lock. It's
+    // probably worthwhile to detect when this happens, and return true in that case, to ensure
+    // that when we return false it really means that no unpark could have been responsible for us
+    // waking up, and that if an unpark call did happen, it woke someone else up.
+    bool didFind = false;
+    dequeue(
+        address, BucketMode::IgnoreEmpty,
+        [&amp;] (ThreadData* element) {
+            if (element == me) {
+                didFind = true;
+                return DequeueResult::RemoveAndStop;
+            }
+            return DequeueResult::Ignore;
+        },
+        [] (bool) { });
+
+    ASSERT(!me-&gt;nextInQueue);
+
+    // Make sure that no matter what, me-&gt;address is null after this point.
+    {
+        std::lock_guard&lt;std::mutex&gt; locker(me-&gt;parkingLock);
+        me-&gt;address = nullptr;
+    }
+
+    // If we were not found in the search above, then we know that someone unparked us.
+    return !didFind;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool ParkingLot::unparkOne(const void* address)
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceWTFwtfParkingLoth"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/ParkingLot.h (188906 => 188907)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/ParkingLot.h        2015-08-25 10:42:37 UTC (rev 188906)
+++ releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/ParkingLot.h        2015-08-25 12:40:25 UTC (rev 188907)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #ifndef WTF_ParkingLot_h
</span><span class="cx"> #define WTF_ParkingLot_h
</span><span class="cx"> 
</span><ins>+#include &lt;chrono&gt;
</ins><span class="cx"> #include &lt;functional&gt;
</span><span class="cx"> #include &lt;wtf/Atomics.h&gt;
</span><span class="cx"> #include &lt;wtf/Threading.h&gt;
</span><span class="lines">@@ -39,10 +40,23 @@
</span><span class="cx"> public:
</span><span class="cx">     // Parks the thread in a queue associated with the given address, which cannot be null. The
</span><span class="cx">     // parking only succeeds if the validation function returns true while the queue lock is held.
</span><del>-    // Returns true if the thread actually slept, or false if it returned quickly because of
-    // validation failure.
-    WTF_EXPORT_PRIVATE static bool parkConditionally(const void* address, std::function&lt;bool()&gt; validation);
</del><ins>+    // If validation returns false, it will unlock the internal parking queue and then it will
+    // return without doing anything else. If validation returns true, it will enqueue the thread,
+    // unlock the parking queue lock, call the beforeSleep function, and then it will sleep so long
+    // as the thread continues to be on the queue and the timeout hasn't fired. Finally, this
+    // returns true if we actually got unparked or false if the timeout was hit. Note that
+    // beforeSleep is called with no locks held, so it's OK to do pretty much anything so long as
+    // you don't recursively call parkConditionally(). You can call unparkOne()/unparkAll() though.
+    // It's useful to use beforeSleep() to unlock some mutex in the implementation of
+    // Condition::wait().
+    WTF_EXPORT_PRIVATE static bool parkConditionally(
+        const void* address,
+        std::function&lt;bool()&gt; validation,
+        std::function&lt;void()&gt; beforeSleep,
+        std::chrono::steady_clock::time_point timeout);
</ins><span class="cx"> 
</span><ins>+    // Simple version of parkConditionally() that covers the most common case: you want to park
+    // indefinitely so long as the value at the given address hasn't changed.
</ins><span class="cx">     template&lt;typename T, typename U&gt;
</span><span class="cx">     static bool compareAndPark(const Atomic&lt;T&gt;* address, U expected)
</span><span class="cx">     {
</span><span class="lines">@@ -51,7 +65,9 @@
</span><span class="cx">             [address, expected] () -&gt; bool {
</span><span class="cx">                 U value = address-&gt;load();
</span><span class="cx">                 return value == expected;
</span><del>-            });
</del><ins>+            },
+            [] () { },
+            std::chrono::steady_clock::time_point::max());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Unparks one thread from the queue associated with the given address, which cannot be null.
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210ToolsChangeLog"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Tools/ChangeLog (188906 => 188907)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Tools/ChangeLog        2015-08-25 10:42:37 UTC (rev 188906)
+++ releases/WebKitGTK/webkit-2.10/Tools/ChangeLog        2015-08-25 12:40:25 UTC (rev 188907)
</span><span class="lines">@@ -1,3 +1,20 @@
</span><ins>+2015-08-13  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        WTF should have a compact Condition object to use with Lock
+        https://bugs.webkit.org/show_bug.cgi?id=147986
+
+        Reviewed by Geoffrey Garen.
+
+        Add a test for WTF::Condition.
+
+        * TestWebKitAPI/CMakeLists.txt:
+        * TestWebKitAPI/TestWebKitAPI.vcxproj/TestWebKitAPI.vcxproj:
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WTF/Condition.cpp: Added.
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WTF/Lock.cpp:
+        (TestWebKitAPI::runLockTest): Change the name of the thread.
+
</ins><span class="cx"> 2015-08-14  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, shorten another test that is timing out.
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210ToolsTestWebKitAPICMakeListstxt"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Tools/TestWebKitAPI/CMakeLists.txt (188906 => 188907)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Tools/TestWebKitAPI/CMakeLists.txt        2015-08-25 10:42:37 UTC (rev 188906)
+++ releases/WebKitGTK/webkit-2.10/Tools/TestWebKitAPI/CMakeLists.txt        2015-08-25 12:40:25 UTC (rev 188907)
</span><span class="lines">@@ -42,6 +42,7 @@
</span><span class="cx">     ${TESTWEBKITAPI_DIR}/TestsController.cpp
</span><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WTF/AtomicString.cpp
</span><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WTF/CString.cpp
</span><ins>+    ${TESTWEBKITAPI_DIR}/Tests/WTF/Condition.cpp
</ins><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WTF/CheckedArithmeticOperations.cpp
</span><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WTF/DateMath.cpp
</span><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WTF/Deque.cpp
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210ToolsTestWebKitAPITestWebKitAPIvcxprojTestWebKitAPIvcxproj"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Tools/TestWebKitAPI/TestWebKitAPI.vcxproj/TestWebKitAPI.vcxproj (188906 => 188907)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Tools/TestWebKitAPI/TestWebKitAPI.vcxproj/TestWebKitAPI.vcxproj        2015-08-25 10:42:37 UTC (rev 188906)
+++ releases/WebKitGTK/webkit-2.10/Tools/TestWebKitAPI/TestWebKitAPI.vcxproj/TestWebKitAPI.vcxproj        2015-08-25 12:40:25 UTC (rev 188907)
</span><span class="lines">@@ -1,4 +1,4 @@
</span><del>-&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
</del><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
</ins><span class="cx"> &lt;Project DefaultTargets=&quot;Build&quot; ToolsVersion=&quot;14.0&quot; xmlns=&quot;http://schemas.microsoft.com/developer/msbuild/2003&quot;&gt;
</span><span class="cx">   &lt;ItemGroup Label=&quot;ProjectConfigurations&quot;&gt;
</span><span class="cx">     &lt;ProjectConfiguration Include=&quot;DebugSuffix|Win32&quot;&gt;
</span><span class="lines">@@ -312,6 +312,7 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\Tests\WTF\cf\RetainPtr.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\Tests\WTF\cf\RetainPtrHashing.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\Tests\WTF\CheckedArithmeticOperations.cpp&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\Tests\WTF\Condition.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\Tests\WTF\CString.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\Tests\WTF\DateMath.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\Tests\WTF\Deque.cpp&quot; /&gt;
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210ToolsTestWebKitAPITestWebKitAPIxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (188906 => 188907)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj        2015-08-25 10:42:37 UTC (rev 188906)
+++ releases/WebKitGTK/webkit-2.10/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj        2015-08-25 12:40:25 UTC (rev 188907)
</span><span class="lines">@@ -12,6 +12,7 @@
</span><span class="cx">                 0F139E791A42457000F590F5 /* PlatformUtilitiesCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F139E721A423A2B00F590F5 /* PlatformUtilitiesCocoa.mm */; };
</span><span class="cx">                 0F3B94A71A77267400DE3272 /* WKWebViewEvaluateJavaScript.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F3B94A51A77266C00DE3272 /* WKWebViewEvaluateJavaScript.mm */; };
</span><span class="cx">                 0FE447991B76F1EB009498EB /* ParkingLot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE447971B76F1E3009498EB /* ParkingLot.cpp */; };
</span><ins>+                0FEAE3691B7D19D200CE17F2 /* Condition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEAE3671B7D19CB00CE17F2 /* Condition.cpp */; };
</ins><span class="cx">                 0FFC45A61B73EBEB0085BD62 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFC45A41B73EBE20085BD62 /* Lock.cpp */; };
</span><span class="cx">                 1A02C870125D4CFD00E3F4BD /* find.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 1A02C84B125D4A5E00E3F4BD /* find.html */; };
</span><span class="cx">                 1A50AA201A2A51FC00F4C345 /* close-from-within-create-page.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 1A50AA1F1A2A4EA500F4C345 /* close-from-within-create-page.html */; };
</span><span class="lines">@@ -431,6 +432,7 @@
</span><span class="cx">                 0FC6C4CB141027E0005B7F0C /* RedBlackTree.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RedBlackTree.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FC6C4CE141034AD005B7F0C /* MetaAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MetaAllocator.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FE447971B76F1E3009498EB /* ParkingLot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParkingLot.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0FEAE3671B7D19CB00CE17F2 /* Condition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Condition.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0FFC45A41B73EBE20085BD62 /* Lock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Lock.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 14464012167A8305000BD218 /* LayoutUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LayoutUnit.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 14F3B11215E45EAB00210069 /* SaturatedArithmeticOperations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SaturatedArithmeticOperations.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -1091,6 +1093,7 @@
</span><span class="cx">                                 BC029B1A1486B23800817DA9 /* ns */,
</span><span class="cx">                                 26F1B44215CA434F00D1E4BF /* AtomicString.cpp */,
</span><span class="cx">                                 A7A966DA140ECCC8005EF9B4 /* CheckedArithmeticOperations.cpp */,
</span><ins>+                                0FEAE3671B7D19CB00CE17F2 /* Condition.cpp */,
</ins><span class="cx">                                 26A2C72E15E2E73C005B1A14 /* CString.cpp */,
</span><span class="cx">                                 E40019301ACE9B5C001B0A2A /* BloomFilter.cpp */,
</span><span class="cx">                                 7AA021BA1AB09EA70052953F /* DateMath.cpp */,
</span><span class="lines">@@ -1494,6 +1497,7 @@
</span><span class="cx">                                 7CCE7EBF1A411A7E00447C4C /* ElementAtPointInWebFrame.mm in Sources */,
</span><span class="cx">                                 7CCE7EEF1A411AE600447C4C /* EphemeralSessionPushStateNoHistoryCallback.cpp in Sources */,
</span><span class="cx">                                 7CCE7EF01A411AE600447C4C /* EvaluateJavaScript.cpp in Sources */,
</span><ins>+                                0FEAE3691B7D19D200CE17F2 /* Condition.cpp in Sources */,
</ins><span class="cx">                                 7CCE7EF11A411AE600447C4C /* FailedLoad.cpp in Sources */,
</span><span class="cx">                                 7CCE7EF31A411AE600447C4C /* Find.cpp in Sources */,
</span><span class="cx">                                 7CCE7EF41A411AE600447C4C /* FindMatches.mm in Sources */,
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210ToolsTestWebKitAPITestsWTFConditioncpp"></a>
<div class="addfile"><h4>Added: releases/WebKitGTK/webkit-2.10/Tools/TestWebKitAPI/Tests/WTF/Condition.cpp (0 => 188907)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Tools/TestWebKitAPI/Tests/WTF/Condition.cpp                                (rev 0)
+++ releases/WebKitGTK/webkit-2.10/Tools/TestWebKitAPI/Tests/WTF/Condition.cpp        2015-08-25 12:40:25 UTC (rev 188907)
</span><span class="lines">@@ -0,0 +1,257 @@
</span><ins>+/*
+ * 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. 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 &quot;config.h&quot;
+#include &lt;mutex&gt;
+#include &lt;thread&gt;
+#include &lt;wtf/Condition.h&gt;
+#include &lt;wtf/DataLog.h&gt;
+#include &lt;wtf/Deque.h&gt;
+#include &lt;wtf/Lock.h&gt;
+#include &lt;wtf/StringPrintStream.h&gt;
+#include &lt;wtf/Threading.h&gt;
+#include &lt;wtf/Vector.h&gt;
+
+using namespace WTF;
+
+namespace TestWebKitAPI {
+
+namespace {
+
+const bool verbose = false;
+
+enum NotifyStyle {
+    AlwaysNotifyOne,
+    TacticallyNotifyAll
+};
+
+template&lt;typename Functor&gt;
+void wait(Condition&amp; condition, std::unique_lock&lt;Lock&gt;&amp; locker, const Functor&amp; predicate, std::chrono::microseconds timeout)
+{
+    if (timeout == std::chrono::microseconds::max())
+        condition.wait(locker, predicate);
+    else {
+        // This tests timeouts in the sense that it verifies that we can call wait() again after a
+        // timeout happened. That's a non-trivial piece of functionality since upon timeout the
+        // ParkingLot has to remove us from the queue.
+        while (!predicate())
+            condition.waitFor(locker, timeout, predicate);
+    }
+}
+
+void notify(NotifyStyle notifyStyle, Condition&amp; condition, bool shouldNotify)
+{
+    switch (notifyStyle) {
+    case AlwaysNotifyOne:
+        condition.notifyOne();
+        break;
+    case TacticallyNotifyAll:
+        if (shouldNotify)
+            condition.notifyAll();
+        break;
+    }
+}
+
+void runTest(
+    unsigned numProducers,
+    unsigned numConsumers,
+    unsigned maxQueueSize,
+    unsigned numMessagesPerProducer,
+    NotifyStyle notifyStyle,
+    std::chrono::microseconds timeout = std::chrono::microseconds::max(),
+    std::chrono::microseconds delay = std::chrono::microseconds::zero())
+{
+    Deque&lt;unsigned&gt; queue;
+    bool shouldContinue = true;
+    Lock lock;
+    Condition emptyCondition;
+    Condition fullCondition;
+
+    Vector&lt;ThreadIdentifier&gt; consumerThreads;
+    Vector&lt;ThreadIdentifier&gt; producerThreads;
+
+    Vector&lt;unsigned&gt; received;
+    Lock receivedLock;
+    
+    for (unsigned i = numConsumers; i--;) {
+        ThreadIdentifier threadIdentifier = createThread(
+            &quot;Consumer thread&quot;,
+            [&amp;] () {
+                for (;;) {
+                    unsigned result;
+                    unsigned shouldNotify = false;
+                    {
+                        std::unique_lock&lt;Lock&gt; locker(lock);
+                        wait(
+                            emptyCondition, locker, 
+                            [&amp;] () {
+                                if (verbose)
+                                    dataLog(toString(currentThread(), &quot;: Checking consumption predicate with shouldContinue = &quot;, shouldContinue, &quot;, queue.size() == &quot;, queue.size(), &quot;\n&quot;));
+                                return !shouldContinue || !queue.isEmpty();
+                            },
+                            timeout);
+                        if (!shouldContinue)
+                            return;
+                        shouldNotify = queue.size() == maxQueueSize;
+                        result = queue.takeFirst();
+                    }
+                    notify(notifyStyle, fullCondition, shouldNotify);
+
+                    {
+                        std::lock_guard&lt;Lock&gt; locker(receivedLock);
+                        received.append(result);
+                    }
+                }
+            });
+        consumerThreads.append(threadIdentifier);
+    }
+
+    std::this_thread::sleep_for(delay);
+
+    for (unsigned i = numProducers; i--;) {
+        ThreadIdentifier threadIdentifier = createThread(
+            &quot;Producer Thread&quot;,
+            [&amp;] () {
+                for (unsigned i = 0; i &lt; numMessagesPerProducer; ++i) {
+                    bool shouldNotify = false;
+                    {
+                        std::unique_lock&lt;Lock&gt; locker(lock);
+                        wait(
+                            fullCondition, locker,
+                            [&amp;] () {
+                                if (verbose)
+                                    dataLog(toString(currentThread(), &quot;: Checking production predicate with shouldContinue = &quot;, shouldContinue, &quot;, queue.size() == &quot;, queue.size(), &quot;\n&quot;));
+                                return queue.size() &lt; maxQueueSize;
+                            },
+                            timeout);
+                        shouldNotify = queue.isEmpty();
+                        queue.append(i);
+                    }
+                    notify(notifyStyle, emptyCondition, shouldNotify);
+                }
+            });
+        producerThreads.append(threadIdentifier);
+    }
+
+    for (ThreadIdentifier threadIdentifier : producerThreads)
+        waitForThreadCompletion(threadIdentifier);
+
+    {
+        std::lock_guard&lt;Lock&gt; locker(lock);
+        shouldContinue = false;
+    }
+    emptyCondition.notifyAll();
+
+    for (ThreadIdentifier threadIdentifier : consumerThreads)
+        waitForThreadCompletion(threadIdentifier);
+
+    EXPECT_EQ(numProducers * numMessagesPerProducer, received.size());
+    std::sort(received.begin(), received.end());
+    for (unsigned messageIndex = 0; messageIndex &lt; numMessagesPerProducer; ++messageIndex) {
+        for (unsigned producerIndex = 0; producerIndex &lt; numProducers; ++producerIndex)
+            EXPECT_EQ(messageIndex, received[messageIndex * numProducers + producerIndex]);
+    }
+}
+
+} // anonymous namespace
+
+TEST(WTF_Condition, OneProducerOneConsumerOneSlot)
+{
+    runTest(1, 1, 1, 100000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, OneProducerOneConsumerOneSlotTimeout)
+{
+    runTest(
+        1, 1, 1, 100000, TacticallyNotifyAll,
+        std::chrono::microseconds(10000),
+        std::chrono::microseconds(1000000));
+}
+
+TEST(WTF_Condition, OneProducerOneConsumerHundredSlots)
+{
+    runTest(1, 1, 100, 1000000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, TenProducersOneConsumerOneSlot)
+{
+    runTest(10, 1, 1, 10000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, TenProducersOneConsumerHundredSlotsNotifyAll)
+{
+    runTest(10, 1, 100, 10000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, TenProducersOneConsumerHundredSlotsNotifyOne)
+{
+    runTest(10, 1, 100, 10000, AlwaysNotifyOne);
+}
+
+TEST(WTF_Condition, OneProducerTenConsumersOneSlot)
+{
+    runTest(1, 10, 1, 10000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, OneProducerTenConsumersHundredSlotsNotifyAll)
+{
+    runTest(1, 10, 100, 100000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, OneProducerTenConsumersHundredSlotsNotifyOne)
+{
+    runTest(1, 10, 100, 100000, AlwaysNotifyOne);
+}
+
+TEST(WTF_Condition, TenProducersTenConsumersOneSlot)
+{
+    runTest(10, 10, 1, 50000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, TenProducersTenConsumersHundredSlotsNotifyAll)
+{
+    runTest(10, 10, 100, 50000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, TenProducersTenConsumersHundredSlotsNotifyOne)
+{
+    runTest(10, 10, 100, 50000, AlwaysNotifyOne);
+}
+
+TEST(WTF_Condition, TimeoutTimesOut)
+{
+    Lock lock;
+    Condition condition;
+
+    lock.lock();
+    bool result = condition.waitFor(
+        lock, std::chrono::microseconds(10000), [] () -&gt; bool { return false; });
+    lock.unlock();
+
+    EXPECT_EQ(false, result);
+}
+
+} // namespace TestWebKitAPI
+
</ins></span></pre></div>
<a id="releasesWebKitGTKwebkit210ToolsTestWebKitAPITestsWTFLockcpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Tools/TestWebKitAPI/Tests/WTF/Lock.cpp (188906 => 188907)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Tools/TestWebKitAPI/Tests/WTF/Lock.cpp        2015-08-25 10:42:37 UTC (rev 188906)
+++ releases/WebKitGTK/webkit-2.10/Tools/TestWebKitAPI/Tests/WTF/Lock.cpp        2015-08-25 12:40:25 UTC (rev 188907)
</span><span class="lines">@@ -53,7 +53,7 @@
</span><span class="cx"> 
</span><span class="cx">         for (unsigned threadIndex = numThreadsPerGroup; threadIndex--;) {
</span><span class="cx">             threads[threadGroupIndex * numThreadsPerGroup + threadIndex] = createThread(
</span><del>-                &quot;Benchmark thread&quot;,
</del><ins>+                &quot;Lock test thread&quot;,
</ins><span class="cx">                 [threadGroupIndex, &amp;locks, &amp;words, numIterations, workPerCriticalSection] () {
</span><span class="cx">                     for (unsigned i = numIterations; i--;) {
</span><span class="cx">                         locks[threadGroupIndex].lock();
</span></span></pre>
</div>
</div>

</body>
</html>