Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(114)

Side by Side Diff: base/synchronization/read_write_lock_unittest.cc

Issue 1988563002: Create a reader-writer lock implementaiton in base. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: move to base::subtle and add a warning Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/synchronization/read_write_lock.h"
6
7 #include <stdlib.h>
8
9 #include "base/compiler_specific.h"
10 #include "base/macros.h"
11 #include "base/synchronization/waitable_event.h"
12 #include "base/threading/platform_thread.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace base {
16 namespace subtle {
17
18 // Basic test to make sure that *Acquire()/*Release() don't crash.
19
20 class BasicReadWriteLockTestThread : public PlatformThread::Delegate {
21 public:
22 explicit BasicReadWriteLockTestThread(ReadWriteLock* lock)
23 : lock_(lock), acquired_(0) {}
24
25 void ThreadMain() override {
26 for (int i = 0; i < 10; i++) {
27 AutoReadLock locker(*lock_);
28 acquired_++;
29 }
30 for (int i = 0; i < 10; i++) {
31 AutoWriteLock locker(*lock_);
32 acquired_++;
33 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
34 }
35 }
36
37 int acquired() const { return acquired_; }
38
39 private:
40 ReadWriteLock* lock_;
41 int acquired_;
42
43 DISALLOW_COPY_AND_ASSIGN(BasicReadWriteLockTestThread);
44 };
45
46 TEST(ReadWriteLockTest, Basic) {
47 ReadWriteLock lock;
48 BasicReadWriteLockTestThread thread(&lock);
49 PlatformThreadHandle handle;
50
51 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
52
53 int acquired = 0;
54 for (int i = 0; i < 5; i++) {
55 AutoReadLock locker(lock);
56 acquired++;
57 }
58 for (int i = 0; i < 10; i++) {
59 AutoWriteLock locker(lock);
60 acquired++;
61 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
62 }
63 for (int i = 0; i < 5; i++) {
64 AutoReadLock locker(lock);
65 acquired++;
66 }
67
68 PlatformThread::Join(handle);
69
70 EXPECT_EQ(20, acquired);
71 EXPECT_GE(20, thread.acquired());
72 }
73
74 // Tests that reader locks allow multiple simultaneous reader acquisitions.
75
76 class ReaderReadWriteLockTestThread : public PlatformThread::Delegate {
77 public:
78 ReaderReadWriteLockTestThread(ReadWriteLock* lock) : lock_(lock) {}
79
80 void ThreadMain() override {
81 AutoReadLock locker(*lock_);
82 did_acquire_ = true;
83 }
84
85 bool did_acquire() const { return did_acquire_; }
86
87 private:
88 ReadWriteLock* lock_;
89 bool did_acquire_ = false;
90
91 DISALLOW_COPY_AND_ASSIGN(ReaderReadWriteLockTestThread);
92 };
93
94 TEST(ReadWriteLockTest, ReaderTwoThreads) {
95 ReadWriteLock lock;
96
97 AutoReadLock auto_lock(lock);
98
99 ReaderReadWriteLockTestThread thread(&lock);
100 PlatformThreadHandle handle;
101
102 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
103 PlatformThread::Join(handle);
104 EXPECT_TRUE(thread.did_acquire());
105 }
106
107 // Tests that writer locks exclude reader locks.
108
109 class ReadAndWriteReadWriteLockTestThread : public PlatformThread::Delegate {
110 public:
111 ReadAndWriteReadWriteLockTestThread(ReadWriteLock* lock, int* value)
112 : lock_(lock), value_(value),
113 event_(true /* manual_reset */, false /* initially_signaled */) {}
114
115 void ThreadMain() override {
116 AutoWriteLock locker(*lock_);
117 (*value_)++;
118 event_.Signal();
119 }
120
121 void Wait() {
122 event_.Wait();
123 }
124
125 private:
126 ReadWriteLock* lock_;
127 int* value_;
128 WaitableEvent event_;
129
130 DISALLOW_COPY_AND_ASSIGN(ReadAndWriteReadWriteLockTestThread);
131 };
132
133 TEST(ReadWriteLockTest, ReadAndWriteThreads) {
134 ReadWriteLock lock;
135 int value = 0;
136
137 ReadAndWriteReadWriteLockTestThread thread(&lock, &value);
138 PlatformThreadHandle handle;
139 {
140 AutoReadLock read_locker(lock);
141 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
142
143 PlatformThread::Sleep(TimeDelta::FromMilliseconds(10));
144
145 // |value| should be unchanged since we hold a reader lock.
146 EXPECT_EQ(0, value);
147 }
148
149 thread.Wait();
150 // After releasing our reader lock, the thread can acquire a write lock and
151 // change |value|.
152 EXPECT_EQ(1, value);
153 PlatformThread::Join(handle);
154 }
155
156 // Tests that writer locks actually exclude.
157
158 class WriterReadWriteLockTestThread : public PlatformThread::Delegate {
159 public:
160 WriterReadWriteLockTestThread(ReadWriteLock* lock, int* value)
161 : lock_(lock), value_(value) {}
162
163 // Static helper which can also be called from the main thread.
164 static void DoStuff(ReadWriteLock* lock, int* value) {
165 for (int i = 0; i < 40; i++) {
166 AutoWriteLock locker(*lock);
167 int v = *value;
168 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 10));
169 *value = v + 1;
170 }
171 }
172
173 void ThreadMain() override { DoStuff(lock_, value_); }
174
175 private:
176 ReadWriteLock* lock_;
177 int* value_;
178
179 DISALLOW_COPY_AND_ASSIGN(WriterReadWriteLockTestThread);
180 };
181
182 TEST(ReadWriteLockTest, MutexTwoThreads) {
183 ReadWriteLock lock;
184 int value = 0;
185
186 WriterReadWriteLockTestThread thread(&lock, &value);
187 PlatformThreadHandle handle;
188
189 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
190
191 WriterReadWriteLockTestThread::DoStuff(&lock, &value);
192
193 PlatformThread::Join(handle);
194
195 EXPECT_EQ(2 * 40, value);
196 }
197
198 TEST(ReadWriteLockTest, MutexFourThreads) {
199 ReadWriteLock lock;
200 int value = 0;
201
202 WriterReadWriteLockTestThread thread1(&lock, &value);
203 WriterReadWriteLockTestThread thread2(&lock, &value);
204 WriterReadWriteLockTestThread thread3(&lock, &value);
205 PlatformThreadHandle handle1;
206 PlatformThreadHandle handle2;
207 PlatformThreadHandle handle3;
208
209 ASSERT_TRUE(PlatformThread::Create(0, &thread1, &handle1));
210 ASSERT_TRUE(PlatformThread::Create(0, &thread2, &handle2));
211 ASSERT_TRUE(PlatformThread::Create(0, &thread3, &handle3));
212
213 WriterReadWriteLockTestThread::DoStuff(&lock, &value);
214
215 PlatformThread::Join(handle1);
216 PlatformThread::Join(handle2);
217 PlatformThread::Join(handle3);
218
219 EXPECT_EQ(4 * 40, value);
220 }
221
222 } // namespace subtle
223 } // namespace base
OLDNEW
« no previous file with comments | « base/synchronization/read_write_lock_posix.cc ('k') | base/synchronization/read_write_lock_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698