Unreviewed, rolling out r234489.
[WebKit-https.git] / Source / WTF / wtf / ReadWriteLock.h
1 /*
2  * Copyright (C) 2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #pragma once
27
28 #include <wtf/Condition.h>
29 #include <wtf/Lock.h>
30
31 namespace WTF {
32
33 // This is a traditional read-write lock implementation that enables concurrency between readers so long as
34 // the read critical section is long. Concurrent readers will experience contention on read().lock() and
35 // read().unlock() if the work inside the critical section is short. The more cores participate in reading,
36 // the longer the read critical section has to be for this locking scheme to be profitable.
37
38 class ReadWriteLock {
39     WTF_MAKE_NONCOPYABLE(ReadWriteLock);
40     WTF_MAKE_FAST_ALLOCATED;
41 public:
42     ReadWriteLock() = default;
43
44     // It's easiest to read lock like this:
45     // 
46     //     auto locker = holdLock(rwLock.read());
47     //
48     // It's easiest to write lock like this:
49     // 
50     //     auto locker = holdLock(rwLock.write());
51     //
52     WTF_EXPORT_PRIVATE void readLock();
53     WTF_EXPORT_PRIVATE void readUnlock();
54     WTF_EXPORT_PRIVATE void writeLock();
55     WTF_EXPORT_PRIVATE void writeUnlock();
56     
57     class ReadLock;
58     class WriteLock;
59
60     ReadLock& read();
61     WriteLock& write();
62
63 private:
64     Lock m_lock;
65     Condition m_cond;
66     bool m_isWriteLocked { false };
67     unsigned m_numReaders { 0 };
68     unsigned m_numWaitingWriters { 0 };
69 };
70
71 class ReadWriteLock::ReadLock : public ReadWriteLock {
72 public:
73     bool tryLock() { return false; }
74     void lock() { readLock(); }
75     void unlock() { readUnlock(); }
76 };
77
78 class ReadWriteLock::WriteLock : public ReadWriteLock {
79 public:
80     bool tryLock() { return false; }
81     void lock() { writeLock(); }
82     void unlock() { writeUnlock(); }
83 };
84     
85 inline ReadWriteLock::ReadLock& ReadWriteLock::read() { return *static_cast<ReadLock*>(this); }
86 inline ReadWriteLock::WriteLock& ReadWriteLock::write() { return *static_cast<WriteLock*>(this); }
87
88 } // namespace WTF
89
90 using WTF::ReadWriteLock;