<!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" /><style type="text/css"><!--
#msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer { 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, #msg p { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; }
#msg ul { overflow: auto; }
#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>
<title>[28979] trunk/WebCore</title>
</head>
<body>

<div id="msg">
<dl>
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/28979">28979</a></dd>
<dt>Author</dt> <dd>mrowe@apple.com</dd>
<dt>Date</dt> <dd>2007-12-24 22:55:23 -0800 (Mon, 24 Dec 2007)</dd>
</dl>

<h3>Log Message</h3>
<pre>Fix Bug 16596: ThreadSafeShared should be lock-free where possible.

Reviewed by Sam Weinig.

Implement a lock-free ThreadSafeShared for i386, x86_64, ppc and ppc64.

This is a 1.7x as fast as the lock-based implementation on x86 for a single-threaded use
of ThreadSafeShared but is closer to 280x as fast when there is heavy concurrent multi-threaded
access to a single ThreadSafeShared object.

The atomic operations are based on those used by the Boost C++ library's shared_ptr implementation.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkWebCoreChangeLog">trunk/WebCore/ChangeLog</a></li>
<li><a href="#trunkWebCoreplatformThreadingh">trunk/WebCore/platform/Threading.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/ChangeLog (28978 => 28979)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/ChangeLog        2007-12-25 06:00:20 UTC (rev 28978)
+++ trunk/WebCore/ChangeLog        2007-12-25 06:55:23 UTC (rev 28979)
</span><span class="lines">@@ -1,3 +1,26 @@
</span><ins>+2007-12-25  Mark Rowe  &lt;mrowe@apple.com&gt;
+
+        Reviewed by Sam Weinig.
+
+        Implement a lock-free ThreadSafeShared for i386, x86_64, ppc and ppc64.
+        http://bugs.webkit.org/show_bug.cgi?id=16596
+
+        This is a 1.7x as fast as the lock-based implementation on x86 for a single-threaded use
+        of ThreadSafeShared but is closer to 280x as fast when there is heavy concurrent multi-threaded
+        access to a single ThreadSafeShared object.
+
+        The atomic operations are based on those used by the Boost C++ library's shared_ptr implementation.
+
+        * platform/Threading.h:
+        (WebCore::atomicIncrement):
+        (WebCore::atomicDecrement):
+        (WebCore::ThreadSafeShared::ThreadSafeShared):
+        (WebCore::ThreadSafeShared::ref): Use lock-free operations if available.
+        (WebCore::ThreadSafeShared::deref): Ditto.
+        (WebCore::ThreadSafeShared::hasOneRef):
+        (WebCore::ThreadSafeShared::refCount):
+        (WebCore::ThreadSafeShared::isThreadSafe):
+
</ins><span class="cx"> 2007-12-24  Darin Adler  &lt;darin@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         * platform/text/PlatformString.h: Removed now-incorrect comment.
</span></span></pre></div>
<a id="trunkWebCoreplatformThreadingh"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/platform/Threading.h (28978 => 28979)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/platform/Threading.h        2007-12-25 06:00:20 UTC (rev 28978)
+++ trunk/WebCore/platform/Threading.h        2007-12-25 06:55:23 UTC (rev 28979)
</span><span class="lines">@@ -25,6 +25,35 @@
</span><span class="cx">  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
</span><span class="cx">  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
</span><span class="cx">  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</span><ins>+ *
+ *
+ * Note: The implementations of InterlockedIncrement and InterlockedDecrement are based
+ * on atomic_increment and atomic_exchange_and_add from the Boost C++ Library. The license
+ * is virtually identical to the Apple license above but is included here for completeness.
+ *
+ * Boost Software License - Version 1.0 - August 17th, 2003
+ * 
+ * Permission is hereby granted, free of charge, to any person or organization
+ * obtaining a copy of the software and accompanying documentation covered by
+ * this license (the &quot;Software&quot;) to use, reproduce, display, distribute,
+ * execute, and transmit the Software, and to prepare derivative works of the
+ * Software, and to permit third-parties to whom the Software is furnished to
+ * do so, all subject to the following:
+ * 
+ * The copyright notices in the Software and this entire statement, including
+ * the above license grant, this restriction and the following disclaimer,
+ * must be included in all copies of the Software, in whole or in part, and
+ * all derivative works of the Software, unless such copies or derivative
+ * works are solely in the form of machine-executable object code generated by
+ * a source language processor.
+ * 
+ * THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+ * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
</ins><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> #ifndef Threading_h
</span><span class="lines">@@ -33,6 +62,10 @@
</span><span class="cx"> #include &lt;wtf/Assertions.h&gt;
</span><span class="cx"> #include &lt;wtf/Noncopyable.h&gt;
</span><span class="cx"> 
</span><ins>+#if PLATFORM(WIN_OS)
+#include &lt;windows.h&gt;
+#endif
+
</ins><span class="cx"> #if USE(PTHREADS)
</span><span class="cx"> #include &lt;pthread.h&gt;
</span><span class="cx"> #endif
</span><span class="lines">@@ -123,60 +156,123 @@
</span><span class="cx"> private:
</span><span class="cx">     PlatformCondition m_condition;
</span><span class="cx"> };
</span><del>-    
</del><ins>+
+#if PLATFORM(WIN_OS)
+#define WTF_USE_LOCKFREE_THREADSAFESHARED 1
+
+inline void atomicIncrement(int volatile* addened) { InterlockedIncrement(addened); }
+inline int atomicDecrement(int volatile* addened) { return InterlockedDecrement(addened); }
+
+#elif COMPILER(GCC) &amp;&amp; (PLATFORM(X86) || PLATFORM(X86_64) || PLATFORM(PPC) || PLATFORM(PPC64))
+#define WTF_USE_LOCKFREE_THREADSAFESHARED 1
+
+inline void atomicIncrement(int volatile* addend)
+{
+#if PLATFORM(X86) || PLATFORM(X86_64)
+    __asm__(
+        &quot;lock\n\t&quot;
+        &quot;incl %0&quot;:
+        &quot;=m&quot;(*addend): // output (%0)
+        &quot;m&quot;(*addend): // input (%1)
+        &quot;cc&quot;
+    );
+#else
+    int tmp;
+    __asm__(
+        &quot;0:\n\t&quot;
+        &quot;lwarx %1, 0, %2\n\t&quot;
+        &quot;addi %1, %1, 1\n\t&quot;
+        &quot;stwcx. %1, 0, %2\n\t&quot;
+        &quot;bne- 0b&quot;:
+
+        &quot;=m&quot;(*addend), &quot;=&amp;b&quot;(tmp):
+        &quot;r&quot;(addend), &quot;m&quot;(*addend):
+        &quot;cc&quot;
+    );
+#endif
+}
+
+inline int atomicDecrement(int volatile* addend)
+{
+#if PLATFORM(X86) || PLATFORM(X86_64)
+    int readval = 0;
+    __asm__ __volatile__
+    (
+        &quot;lock\n\t&quot;
+        &quot;xadd %1, %0&quot;:
+        &quot;=m&quot;(*addend), &quot;=r&quot;(readval): // outputs (%0, %1)
+        &quot;m&quot;(*addend), &quot;1&quot;(-1): // inputs (%2, %3 == %1)
+        &quot;memory&quot;, &quot;cc&quot; // clobbers
+    );
+    return readval - 1;
+#else
+    int readval;
+    __asm__ __volatile__(
+        &quot;sync\n\t&quot;
+        &quot;0:\n\t&quot;
+        &quot;lwarx %1, 0, %2\n\t&quot;
+        &quot;addi %1, %1, -1\n\t&quot;
+        &quot;stwcx. %1, 0, %2\n\t&quot;
+        &quot;bne- 0b\n\t&quot;
+        &quot;isync&quot;:
+
+        &quot;=m&quot;(*addend), &quot;=&amp;b&quot;(readval):
+        &quot;r&quot;(addend), &quot;m&quot;(*addend):
+        &quot;memory&quot;, &quot;cc&quot;
+    );
+    return readval;
+#endif
+}
+#endif
+
</ins><span class="cx"> template&lt;class T&gt; class ThreadSafeShared : Noncopyable {
</span><span class="cx"> public:
</span><span class="cx">     ThreadSafeShared()
</span><span class="cx">         : m_refCount(0)
</span><del>-#ifndef NDEBUG
-        , m_inDestructor(0)
-#endif
</del><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void ref()
</span><span class="cx">     {
</span><ins>+#if USE(LOCKFREE_THREADSAFESHARED)
+        atomicIncrement(&amp;m_refCount);
+#else
</ins><span class="cx">         MutexLocker locker(m_mutex);
</span><del>-        ASSERT(!m_inDestructor);
</del><span class="cx">         ++m_refCount;
</span><ins>+#endif
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void deref()
</span><span class="cx">     {
</span><ins>+#if USE(LOCKFREE_THREADSAFESHARED)
+        if (atomicDecrement(&amp;m_refCount) &lt;= 0)
+#else
</ins><span class="cx">         {
</span><span class="cx">             MutexLocker locker(m_mutex);
</span><del>-            ASSERT(!m_inDestructor);
</del><span class="cx">             --m_refCount;
</span><span class="cx">         }
</span><del>-        
-        if (m_refCount &lt;= 0) {
-#ifndef NDEBUG
-            m_inDestructor = true;
</del><ins>+        if (m_refCount &lt;= 0)
</ins><span class="cx"> #endif
</span><span class="cx">             delete static_cast&lt;T*&gt;(this);
</span><del>-        }
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool hasOneRef()
</span><span class="cx">     {
</span><del>-        MutexLocker locker(m_mutex);
-        ASSERT(!m_inDestructor);
-        return m_refCount == 1;
</del><ins>+        return refCount() == 1;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     int refCount() const
</span><span class="cx">     {
</span><ins>+#if !USE(LOCKFREE_THREADSAFESHARED)
</ins><span class="cx">         MutexLocker locker(m_mutex);
</span><del>-        return m_refCount;
</del><ins>+#endif
+        return static_cast&lt;int const volatile &amp;&gt;(m_refCount);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool isThreadSafe() { return true; }
-    
</del><span class="cx"> private:
</span><ins>+    int m_refCount;
+#if !USE(LOCKFREE_THREADSAFESHARED)
</ins><span class="cx">     mutable Mutex m_mutex;
</span><del>-    int m_refCount;
-#ifndef NDEBUG
-    bool m_inDestructor;
</del><span class="cx"> #endif
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>