summaryrefslogtreecommitdiff
path: root/Source/WTF/wtf/Lock.h
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WTF/wtf/Lock.h
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WTF/wtf/Lock.h')
-rw-r--r--Source/WTF/wtf/Lock.h153
1 files changed, 153 insertions, 0 deletions
diff --git a/Source/WTF/wtf/Lock.h b/Source/WTF/wtf/Lock.h
new file mode 100644
index 000000000..9dec84c1f
--- /dev/null
+++ b/Source/WTF/wtf/Lock.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2015-2016 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_Lock_h
+#define WTF_Lock_h
+
+#include <wtf/LockAlgorithm.h>
+#include <wtf/Locker.h>
+#include <wtf/Noncopyable.h>
+
+namespace TestWebKitAPI {
+struct LockInspector;
+};
+
+namespace WTF {
+
+typedef LockAlgorithm<uint8_t, 1, 2> DefaultLockAlgorithm;
+
+// This is a fully adaptive mutex that only requires 1 byte of storage. It has fast paths that are
+// competetive to a spinlock (uncontended locking is inlined and is just a CAS, microcontention is
+// handled by spinning and yielding), and a slow path that is competetive to std::mutex (if a lock
+// cannot be acquired in a short period of time, the thread is put to sleep until the lock is
+// available again). It uses less memory than a std::mutex. This lock guarantees eventual stochastic
+// fairness, even in programs that relock the lock immediately after unlocking it. Except when there
+// are collisions between this lock and other locks in the ParkingLot, this lock will guarantee that
+// at worst one call to unlock() per millisecond will do a direct hand-off to the thread that is at
+// the head of the queue. When there are collisions, each collision increases the fair unlock delay
+// by one millisecond in the worst case.
+
+// This is a struct without a constructor or destructor so that it can be statically initialized.
+// Use Lock in instance variables.
+struct LockBase {
+ void lock()
+ {
+ if (UNLIKELY(!DefaultLockAlgorithm::lockFastAssumingZero(m_byte)))
+ lockSlow();
+ }
+
+ bool tryLock()
+ {
+ return DefaultLockAlgorithm::tryLock(m_byte);
+ }
+
+ // Need this version for std::unique_lock.
+ bool try_lock()
+ {
+ return tryLock();
+ }
+
+ // Relinquish the lock. Either one of the threads that were waiting for the lock, or some other
+ // thread that happens to be running, will be able to grab the lock. This bit of unfairness is
+ // called barging, and we allow it because it maximizes throughput. However, we bound how unfair
+ // barging can get by ensuring that every once in a while, when there is a thread waiting on the
+ // lock, we hand the lock to that thread directly. Every time unlock() finds a thread waiting,
+ // we check if the last time that we did a fair unlock was more than roughly 1ms ago; if so, we
+ // unlock fairly. Fairness matters most for long critical sections, and this virtually
+ // guarantees that long critical sections always get a fair lock.
+ void unlock()
+ {
+ if (UNLIKELY(!DefaultLockAlgorithm::unlockFastAssumingZero(m_byte)))
+ unlockSlow();
+ }
+
+ // This is like unlock() but it guarantees that we unlock the lock fairly. For short critical
+ // sections, this is much slower than unlock(). For long critical sections, unlock() will learn
+ // to be fair anyway. However, if you plan to relock the lock right after unlocking and you want
+ // to ensure that some other thread runs in the meantime, this is probably the function you
+ // want.
+ void unlockFairly()
+ {
+ if (UNLIKELY(!DefaultLockAlgorithm::unlockFastAssumingZero(m_byte)))
+ unlockFairlySlow();
+ }
+
+ void safepoint()
+ {
+ if (UNLIKELY(!DefaultLockAlgorithm::safepointFast(m_byte)))
+ safepointSlow();
+ }
+
+ bool isHeld() const
+ {
+ return DefaultLockAlgorithm::isLocked(m_byte);
+ }
+
+ bool isLocked() const
+ {
+ return isHeld();
+ }
+
+protected:
+ friend struct TestWebKitAPI::LockInspector;
+
+ static const uint8_t isHeldBit = 1;
+ static const uint8_t hasParkedBit = 2;
+
+ WTF_EXPORT_PRIVATE void lockSlow();
+ WTF_EXPORT_PRIVATE void unlockSlow();
+ WTF_EXPORT_PRIVATE void unlockFairlySlow();
+ WTF_EXPORT_PRIVATE void safepointSlow();
+
+ // Method used for testing only.
+ bool isFullyReset() const
+ {
+ return !m_byte.load();
+ }
+
+ Atomic<uint8_t> m_byte;
+};
+
+class Lock : public LockBase {
+ WTF_MAKE_NONCOPYABLE(Lock);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ Lock()
+ {
+ m_byte.store(0, std::memory_order_relaxed);
+ }
+};
+
+typedef LockBase StaticLock;
+typedef Locker<LockBase> LockHolder;
+
+} // namespace WTF
+
+using WTF::Lock;
+using WTF::LockHolder;
+using WTF::StaticLock;
+
+#endif // WTF_Lock_h
+