OLD | NEW |
---|---|
(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/rw_lock.h" | |
6 | |
7 #include <stdlib.h> | |
8 | |
9 #include "base/compiler_specific.h" | |
10 #include "base/macros.h" | |
11 #include "base/threading/platform_thread.h" | |
12 #include "testing/gtest/include/gtest/gtest.h" | |
13 | |
14 namespace base { | |
15 | |
16 // Basic test to make sure that *Acquire()/*Release() don't crash ---------- | |
danakj
2016/05/19 23:01:37
replace the " ----------" with "." and ditto elsew
Anand Mistry (off Chromium)
2016/05/20 04:06:39
Done.
| |
17 | |
18 class BasicRWLockTestThread : public PlatformThread::Delegate { | |
19 public: | |
20 explicit BasicRWLockTestThread(RWLock* lock) : lock_(lock), acquired_(0) {} | |
21 | |
22 void ThreadMain() override { | |
23 for (int i = 0; i < 10; i++) { | |
24 lock_->ReadAcquire(); | |
25 acquired_++; | |
26 lock_->ReadRelease(); | |
27 } | |
28 for (int i = 0; i < 10; i++) { | |
29 lock_->WriteAcquire(); | |
30 acquired_++; | |
31 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20)); | |
32 lock_->WriteRelease(); | |
33 } | |
34 } | |
35 | |
36 int acquired() const { return acquired_; } | |
37 | |
38 private: | |
39 RWLock* lock_; | |
40 int acquired_; | |
41 | |
42 DISALLOW_COPY_AND_ASSIGN(BasicRWLockTestThread); | |
43 }; | |
44 | |
45 TEST(RWLockTest, Basic) { | |
46 RWLock lock; | |
47 BasicRWLockTestThread thread(&lock); | |
48 PlatformThreadHandle handle; | |
49 | |
50 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); | |
51 | |
52 int acquired = 0; | |
53 for (int i = 0; i < 5; i++) { | |
danakj
2016/05/19 23:01:37
I don't really get the point of this test. What is
Anand Mistry (off Chromium)
2016/05/20 04:06:39
It's a basic sanity test to ensure that acquisitio
| |
54 lock.ReadAcquire(); | |
55 acquired++; | |
56 lock.ReadRelease(); | |
57 } | |
58 for (int i = 0; i < 10; i++) { | |
59 lock.WriteAcquire(); | |
60 acquired++; | |
61 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20)); | |
62 lock.WriteRelease(); | |
63 } | |
64 for (int i = 0; i < 5; i++) { | |
65 lock.ReadAcquire(); | |
66 acquired++; | |
67 lock.ReadRelease(); | |
68 } | |
69 | |
70 PlatformThread::Join(handle); | |
71 | |
72 EXPECT_EQ(20, acquired); | |
73 EXPECT_GE(20, thread.acquired()); | |
74 } | |
75 | |
76 // Tests that reader locks allow multiple simultaneous acquisitions --------- | |
77 | |
78 class ReaderRWLockTestThread : public PlatformThread::Delegate { | |
79 public: | |
80 ReaderRWLockTestThread(RWLock* lock) : lock_(lock) {} | |
81 | |
82 void ThreadMain() override { | |
83 lock_->ReadAcquire(); | |
danakj
2016/05/19 23:01:37
Use AutoReadLock
Anand Mistry (off Chromium)
2016/05/20 04:06:39
Done.
| |
84 did_acquire_ = true; | |
85 lock_->ReadRelease(); | |
86 } | |
87 | |
88 bool did_acquire() const { return did_acquire_; } | |
89 | |
90 private: | |
91 RWLock* lock_; | |
92 bool did_acquire_ = false; | |
93 | |
94 DISALLOW_COPY_AND_ASSIGN(ReaderRWLockTestThread); | |
95 }; | |
96 | |
97 TEST(RWLockTest, ReaderTwoThreads) { | |
98 RWLock lock; | |
99 | |
100 AutoReadLock auto_lock(lock); | |
101 | |
102 ReaderRWLockTestThread thread(&lock); | |
103 PlatformThreadHandle handle; | |
104 | |
105 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); | |
106 PlatformThread::Join(handle); | |
107 EXPECT_TRUE(thread.did_acquire()); | |
108 } | |
109 | |
110 // Tests that writer locks actually exclude --------------------------------- | |
111 | |
112 class WriterRWLockTestThread : public PlatformThread::Delegate { | |
113 public: | |
114 WriterRWLockTestThread(RWLock* lock, int* value) | |
115 : lock_(lock), value_(value) {} | |
116 | |
117 // Static helper which can also be called from the main thread. | |
118 static void DoStuff(RWLock* lock, int* value) { | |
119 for (int i = 0; i < 40; i++) { | |
120 lock->WriteAcquire(); | |
121 int v = *value; | |
122 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 10)); | |
123 *value = v + 1; | |
124 lock->WriteRelease(); | |
125 } | |
126 } | |
127 | |
128 void ThreadMain() override { DoStuff(lock_, value_); } | |
129 | |
130 private: | |
131 RWLock* lock_; | |
132 int* value_; | |
133 | |
134 DISALLOW_COPY_AND_ASSIGN(WriterRWLockTestThread); | |
135 }; | |
136 | |
137 TEST(RWLockTest, MutexTwoThreads) { | |
138 RWLock lock; | |
139 int value = 0; | |
140 | |
141 WriterRWLockTestThread thread(&lock, &value); | |
142 PlatformThreadHandle handle; | |
143 | |
144 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); | |
145 | |
146 WriterRWLockTestThread::DoStuff(&lock, &value); | |
danakj
2016/05/19 23:01:37
This seems like you could write a bit more obvious
Anand Mistry (off Chromium)
2016/05/20 04:06:38
Done.
| |
147 | |
148 PlatformThread::Join(handle); | |
149 | |
150 EXPECT_EQ(2 * 40, value); | |
151 } | |
152 | |
153 TEST(RWLockTest, MutexFourThreads) { | |
154 RWLock lock; | |
155 int value = 0; | |
156 | |
157 WriterRWLockTestThread thread1(&lock, &value); | |
158 WriterRWLockTestThread thread2(&lock, &value); | |
159 WriterRWLockTestThread thread3(&lock, &value); | |
160 PlatformThreadHandle handle1; | |
161 PlatformThreadHandle handle2; | |
162 PlatformThreadHandle handle3; | |
163 | |
164 ASSERT_TRUE(PlatformThread::Create(0, &thread1, &handle1)); | |
165 ASSERT_TRUE(PlatformThread::Create(0, &thread2, &handle2)); | |
166 ASSERT_TRUE(PlatformThread::Create(0, &thread3, &handle3)); | |
167 | |
168 WriterRWLockTestThread::DoStuff(&lock, &value); | |
169 | |
170 PlatformThread::Join(handle1); | |
171 PlatformThread::Join(handle2); | |
172 PlatformThread::Join(handle3); | |
173 | |
174 EXPECT_EQ(4 * 40, value); | |
175 } | |
176 | |
177 } // namespace base | |
OLD | NEW |