<!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>[188910] releases/WebKitGTK/webkit-2.10/Source/WTF</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/188910">188910</a></dd>
<dt>Author</dt> <dd>carlosgc@webkit.org</dd>
<dt>Date</dt> <dd>2015-08-25 09:17:35 -0700 (Tue, 25 Aug 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/188605">r188605</a> - WTF::Condition should have a fast path for notifyOne/notifyAll that avoids calling unparkOne/unparkAll
https://bugs.webkit.org/show_bug.cgi?id=148090
Reviewed by Geoffrey Garen.
This change makes notifyOne()/notifyAll() blazing fast when nobody is waiting, by using the
various hooks that ParkingLot gives us to maintain a m_hasWaiters variable. When it's false, it
means that any unpark operation would simply return immediately.
This is a 45% speed-up for the 1-producer/1-consumer scenario with a 100-element queue when you
use the notifyOne()-per-enqueue style. What's cool about this change is that you can now safely
call notifyOne() (or notifyAll()) out of paranoia, just in case someone might be waiting. It's
free to do so if nobody is waiting!
* wtf/Condition.h:
(WTF::Condition::Condition):
(WTF::Condition::waitUntil):
(WTF::Condition::notifyOne):
(WTF::Condition::notifyAll):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit210SourceWTFChangeLog">releases/WebKitGTK/webkit-2.10/Source/WTF/ChangeLog</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceWTFwtfConditionh">releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/Condition.h</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 (188909 => 188910)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/WTF/ChangeLog        2015-08-25 15:50:51 UTC (rev 188909)
+++ releases/WebKitGTK/webkit-2.10/Source/WTF/ChangeLog        2015-08-25 16:17:35 UTC (rev 188910)
</span><span class="lines">@@ -1,3 +1,25 @@
</span><ins>+2015-08-18 Filip Pizlo <fpizlo@apple.com>
+
+ WTF::Condition should have a fast path for notifyOne/notifyAll that avoids calling unparkOne/unparkAll
+ https://bugs.webkit.org/show_bug.cgi?id=148090
+
+ Reviewed by Geoffrey Garen.
+
+ This change makes notifyOne()/notifyAll() blazing fast when nobody is waiting, by using the
+ various hooks that ParkingLot gives us to maintain a m_hasWaiters variable. When it's false, it
+ means that any unpark operation would simply return immediately.
+
+ This is a 45% speed-up for the 1-producer/1-consumer scenario with a 100-element queue when you
+ use the notifyOne()-per-enqueue style. What's cool about this change is that you can now safely
+ call notifyOne() (or notifyAll()) out of paranoia, just in case someone might be waiting. It's
+ free to do so if nobody is waiting!
+
+ * wtf/Condition.h:
+ (WTF::Condition::Condition):
+ (WTF::Condition::waitUntil):
+ (WTF::Condition::notifyOne):
+ (WTF::Condition::notifyAll):
+
</ins><span class="cx"> 2015-08-17 Filip Pizlo <fpizlo@apple.com>
</span><span class="cx">
</span><span class="cx"> Replace all remaining uses of WTF::Mutex with WTF::Lock
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceWTFwtfConditionh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/Condition.h (188909 => 188910)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/Condition.h        2015-08-25 15:50:51 UTC (rev 188909)
+++ releases/WebKitGTK/webkit-2.10/Source/WTF/wtf/Condition.h        2015-08-25 16:17:35 UTC (rev 188910)
</span><span class="lines">@@ -38,7 +38,10 @@
</span><span class="cx"> public:
</span><span class="cx"> typedef ParkingLot::Clock Clock;
</span><span class="cx">
</span><del>- Condition() { }
</del><ins>+ Condition()
+ {
+ m_hasWaiters.store(false);
+ }
</ins><span class="cx">
</span><span class="cx"> // Wait on a parking queue while releasing the given lock. It will unlock the lock just before
</span><span class="cx"> // parking, and relock it upon wakeup. Returns true if we woke up due to some call to
</span><span class="lines">@@ -64,8 +67,13 @@
</span><span class="cx"> result = false;
</span><span class="cx"> } else {
</span><span class="cx"> result = ParkingLot::parkConditionally(
</span><del>- &m_dummy,
- [] () -> bool { return true; },
</del><ins>+ &m_hasWaiters,
+ [this] () -> bool {
+ // Let everyone know that we will be waiting. Do this while we hold the queue lock,
+ // to prevent races with notifyOne().
+ m_hasWaiters.store(true);
+ return true;
+ },
</ins><span class="cx"> [&lock] () { lock.unlock(); },
</span><span class="cx"> timeout);
</span><span class="cx"> }
</span><span class="lines">@@ -129,18 +137,39 @@
</span><span class="cx"> return waitForSecondsImpl(lock, absoluteTimeoutSeconds - monotonicallyIncreasingTime());
</span><span class="cx"> }
</span><span class="cx">
</span><del>- // FIXME: We could replace the dummy byte with a boolean to tell us if there is anyone waiting
- // right now. This could be used to implement a fast path for notifyOne() and notifyAll().
- // https://bugs.webkit.org/show_bug.cgi?id=148090
-
</del><ins>+ // Note that this method is extremely fast when nobody is waiting. It is not necessary to try to
+ // avoid calling this method.
</ins><span class="cx"> void notifyOne()
</span><span class="cx"> {
</span><del>- ParkingLot::unparkOne(&m_dummy);
</del><ins>+ if (!m_hasWaiters.load()) {
+ // At this exact instant, there is nobody waiting on this condition. The way to visualize
+ // this is that if unparkOne() ran to completion without obstructions at this moment, it
+ // wouldn't wake anyone up. Hence, we have nothing to do!
+ return;
+ }
+
+ ParkingLot::unparkOne(
+ &m_hasWaiters,
+ [this] (bool, bool mayHaveMoreThreads) {
+ if (!mayHaveMoreThreads)
+ m_hasWaiters.store(false);
+ });
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void notifyAll()
</span><span class="cx"> {
</span><del>- ParkingLot::unparkAll(&m_dummy);
</del><ins>+ if (!m_hasWaiters.load()) {
+ // See above.
+ return;
+ }
+
+ // It's totally safe for us to set this to false without any locking, because this thread is
+ // guaranteed to then unparkAll() anyway. So, if there is a race with some thread calling
+ // wait() just before this store happens, that thread is guaranteed to be awoken by the call to
+ // unparkAll(), below.
+ m_hasWaiters.store(false);
+
+ ParkingLot::unparkAll(&m_hasWaiters);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> private:
</span><span class="lines">@@ -194,7 +223,7 @@
</span><span class="cx"> return Clock::now() + myRelativeTimeout;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- uint8_t m_dummy;
</del><ins>+ Atomic<bool> m_hasWaiters;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> } // namespace WTF
</span></span></pre>
</div>
</div>
</body>
</html>