| /* |
| * Copyright (C) 2017 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. |
| */ |
| |
| #pragma once |
| |
| #include <wtf/Condition.h> |
| #include <wtf/Lock.h> |
| |
| namespace WTF { |
| |
| // This is a traditional read-write lock implementation that enables concurrency between readers so long as |
| // the read critical section is long. Concurrent readers will experience contention on read().lock() and |
| // read().unlock() if the work inside the critical section is short. The more cores participate in reading, |
| // the longer the read critical section has to be for this locking scheme to be profitable. |
| |
| class ReadWriteLock { |
| WTF_MAKE_NONCOPYABLE(ReadWriteLock); |
| WTF_MAKE_FAST_ALLOCATED; |
| public: |
| ReadWriteLock() = default; |
| |
| // It's easiest to read lock like this: |
| // |
| // auto locker = holdLock(rwLock.read()); |
| // |
| // It's easiest to write lock like this: |
| // |
| // auto locker = holdLock(rwLock.write()); |
| // |
| WTF_EXPORT_PRIVATE void readLock(); |
| WTF_EXPORT_PRIVATE void readUnlock(); |
| WTF_EXPORT_PRIVATE void writeLock(); |
| WTF_EXPORT_PRIVATE void writeUnlock(); |
| |
| class ReadLock; |
| class WriteLock; |
| |
| ReadLock& read(); |
| WriteLock& write(); |
| |
| private: |
| Lock m_lock; |
| Condition m_cond; |
| bool m_isWriteLocked { false }; |
| unsigned m_numReaders { 0 }; |
| unsigned m_numWaitingWriters { 0 }; |
| }; |
| |
| class ReadWriteLock::ReadLock : public ReadWriteLock { |
| public: |
| bool tryLock() { return false; } |
| void lock() { readLock(); } |
| void unlock() { readUnlock(); } |
| }; |
| |
| class ReadWriteLock::WriteLock : public ReadWriteLock { |
| public: |
| bool tryLock() { return false; } |
| void lock() { writeLock(); } |
| void unlock() { writeUnlock(); } |
| }; |
| |
| inline ReadWriteLock::ReadLock& ReadWriteLock::read() { return *static_cast<ReadLock*>(this); } |
| inline ReadWriteLock::WriteLock& ReadWriteLock::write() { return *static_cast<WriteLock*>(this); } |
| |
| } // namespace WTF |
| |
| using WTF::ReadWriteLock; |