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

Side by Side Diff: rlz/lib/recursive_lock_unittest.cc

Issue 11361057: [cros] Add RecursiveLock for CrOS implementation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Merge Created 8 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « rlz/lib/recursive_lock.cc ('k') | rlz/rlz.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/synchronization/lock.h" 5 #include "rlz/lib/recursive_lock.h"
6 6
7 #include <stdlib.h> 7 #include <stdlib.h>
8 8
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/threading/platform_thread.h" 10 #include "base/threading/platform_thread.h"
11 #include "base/time.h"
11 #include "testing/gtest/include/gtest/gtest.h" 12 #include "testing/gtest/include/gtest/gtest.h"
12 13
13 namespace base { 14 using base::kNullThreadHandle;
15 using base::PlatformThread;
16 using base::PlatformThreadHandle;
17 using base::TimeDelta;
14 18
15 // Basic test to make sure that Acquire()/Release()/Try() don't crash ---------- 19 namespace rlz_lib {
16 20
21 // Basic test to make sure that Acquire()/Release() don't crash.
17 class BasicLockTestThread : public PlatformThread::Delegate { 22 class BasicLockTestThread : public PlatformThread::Delegate {
18 public: 23 public:
19 BasicLockTestThread(Lock* lock) : lock_(lock), acquired_(0) {} 24 BasicLockTestThread(RecursiveLock* lock) : lock_(lock), acquired_(0) {}
20 25
21 virtual void ThreadMain() OVERRIDE { 26 virtual void ThreadMain() OVERRIDE {
22 for (int i = 0; i < 10; i++) { 27 for (int i = 0; i < 10; i++) {
23 lock_->Acquire(); 28 lock_->Acquire();
24 acquired_++; 29 acquired_++;
25 lock_->Release(); 30 lock_->Release();
26 } 31 }
27 for (int i = 0; i < 10; i++) { 32 for (int i = 0; i < 10; i++) {
28 lock_->Acquire(); 33 lock_->Acquire();
29 acquired_++; 34 acquired_++;
30 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20)); 35 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
31 lock_->Release(); 36 lock_->Release();
32 } 37 }
33 for (int i = 0; i < 10; i++) {
34 if (lock_->Try()) {
35 acquired_++;
36 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
37 lock_->Release();
38 }
39 }
40 } 38 }
41 39
42 int acquired() const { return acquired_; } 40 int acquired() const { return acquired_; }
43 41
44 private: 42 private:
45 Lock* lock_; 43 RecursiveLock* lock_;
46 int acquired_; 44 int acquired_;
47 45
48 DISALLOW_COPY_AND_ASSIGN(BasicLockTestThread); 46 DISALLOW_COPY_AND_ASSIGN(BasicLockTestThread);
49 }; 47 };
50 48
51 TEST(LockTest, Basic) { 49 TEST(RecursiveLockTest, Basic) {
52 Lock lock; 50 RecursiveLock lock;
53 BasicLockTestThread thread(&lock); 51 BasicLockTestThread thread(&lock);
54 PlatformThreadHandle handle = kNullThreadHandle; 52 PlatformThreadHandle handle = kNullThreadHandle;
55 53
56 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); 54 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
57 55
58 int acquired = 0; 56 int acquired = 0;
59 for (int i = 0; i < 5; i++) { 57 for (int i = 0; i < 5; i++) {
60 lock.Acquire(); 58 lock.Acquire();
61 acquired++; 59 acquired++;
62 lock.Release(); 60 lock.Release();
63 } 61 }
64 for (int i = 0; i < 10; i++) { 62 for (int i = 0; i < 10; i++) {
65 lock.Acquire(); 63 lock.Acquire();
66 acquired++; 64 acquired++;
67 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20)); 65 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
68 lock.Release(); 66 lock.Release();
69 } 67 }
70 for (int i = 0; i < 10; i++) {
71 if (lock.Try()) {
72 acquired++;
73 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
74 lock.Release();
75 }
76 }
77 for (int i = 0; i < 5; i++) { 68 for (int i = 0; i < 5; i++) {
78 lock.Acquire(); 69 lock.Acquire();
79 acquired++; 70 acquired++;
80 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20)); 71 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
81 lock.Release(); 72 lock.Release();
82 } 73 }
83 74
84 PlatformThread::Join(handle); 75 PlatformThread::Join(handle);
85 76
86 EXPECT_GE(acquired, 20); 77 EXPECT_EQ(acquired, 20);
87 EXPECT_GE(thread.acquired(), 20); 78 EXPECT_EQ(thread.acquired(), 20);
88 } 79 }
89 80
90 // Test that Try() works as expected ------------------------------------------- 81 // Tests that locks are actually exclusive.
91 82 class MutexLockTestThread : public PlatformThread::Delegate {
92 class TryLockTestThread : public PlatformThread::Delegate {
93 public: 83 public:
94 TryLockTestThread(Lock* lock) : lock_(lock), got_lock_(false) {} 84 MutexLockTestThread(RecursiveLock* lock, int* value)
95 85 : lock_(lock),
96 virtual void ThreadMain() OVERRIDE { 86 value_(value) {
97 got_lock_ = lock_->Try();
98 if (got_lock_)
99 lock_->Release();
100 } 87 }
101 88
102 bool got_lock() const { return got_lock_; }
103
104 private:
105 Lock* lock_;
106 bool got_lock_;
107
108 DISALLOW_COPY_AND_ASSIGN(TryLockTestThread);
109 };
110
111 TEST(LockTest, TryLock) {
112 Lock lock;
113
114 ASSERT_TRUE(lock.Try());
115 // We now have the lock....
116
117 // This thread will not be able to get the lock.
118 {
119 TryLockTestThread thread(&lock);
120 PlatformThreadHandle handle = kNullThreadHandle;
121
122 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
123
124 PlatformThread::Join(handle);
125
126 ASSERT_FALSE(thread.got_lock());
127 }
128
129 lock.Release();
130
131 // This thread will....
132 {
133 TryLockTestThread thread(&lock);
134 PlatformThreadHandle handle = kNullThreadHandle;
135
136 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
137
138 PlatformThread::Join(handle);
139
140 ASSERT_TRUE(thread.got_lock());
141 // But it released it....
142 ASSERT_TRUE(lock.Try());
143 }
144
145 lock.Release();
146 }
147
148 // Tests that locks actually exclude -------------------------------------------
149
150 class MutexLockTestThread : public PlatformThread::Delegate {
151 public:
152 MutexLockTestThread(Lock* lock, int* value) : lock_(lock), value_(value) {}
153
154 // Static helper which can also be called from the main thread. 89 // Static helper which can also be called from the main thread.
155 static void DoStuff(Lock* lock, int* value) { 90 static void DoStuff(RecursiveLock* lock, int* value) {
156 for (int i = 0; i < 40; i++) { 91 for (int i = 0; i < 40; i++) {
157 lock->Acquire(); 92 lock->Acquire();
158 int v = *value; 93 int v = *value;
159 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 10)); 94 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 10));
160 *value = v + 1; 95 *value = v + 1;
161 lock->Release(); 96 lock->Release();
162 } 97 }
163 } 98 }
99
100 virtual void ThreadMain() OVERRIDE {
101 DoStuff(lock_, value_);
102 }
103
104 private:
105 RecursiveLock* lock_;
106 int* value_;
107
108 DISALLOW_COPY_AND_ASSIGN(MutexLockTestThread);
109 };
110
111 TEST(RecursiveLockTest, MutexTwoThreads) {
112 RecursiveLock lock;
113 int value = 0;
114
115 MutexLockTestThread thread(&lock, &value);
116 PlatformThreadHandle handle = kNullThreadHandle;
117
118 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
119
120 MutexLockTestThread::DoStuff(&lock, &value);
121
122 PlatformThread::Join(handle);
123
124 EXPECT_EQ(2 * 40, value);
125 }
126
127 TEST(RecursiveLockTest, MutexFourThreads) {
128 RecursiveLock lock;
129 int value = 0;
130
131 MutexLockTestThread thread1(&lock, &value);
132 MutexLockTestThread thread2(&lock, &value);
133 MutexLockTestThread thread3(&lock, &value);
134 PlatformThreadHandle handle1 = kNullThreadHandle;
135 PlatformThreadHandle handle2 = kNullThreadHandle;
136 PlatformThreadHandle handle3 = kNullThreadHandle;
137
138 ASSERT_TRUE(PlatformThread::Create(0, &thread1, &handle1));
139 ASSERT_TRUE(PlatformThread::Create(0, &thread2, &handle2));
140 ASSERT_TRUE(PlatformThread::Create(0, &thread3, &handle3));
141
142 MutexLockTestThread::DoStuff(&lock, &value);
143
144 PlatformThread::Join(handle1);
145 PlatformThread::Join(handle2);
146 PlatformThread::Join(handle3);
147
148 EXPECT_EQ(4 * 40, value);
149 }
150
151 // Tests that locks are recursive.
152 class MutexRecursiveLockTestThread : public PlatformThread::Delegate {
153 public:
154 MutexRecursiveLockTestThread(RecursiveLock* lock, int* value)
155 : lock_(lock),
156 value_(value) {
157 }
158
159 // Static helper which can also be called from the main thread.
160 static void DoStuff(RecursiveLock* lock, int* value) {
161 for (int i = 0; i < 20; i++) {
162 // First lock.
163 lock->Acquire();
164 int v = *value;
165 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 10));
166 *value = v + 1;
167 {
168 // Recursive lock.
169 lock->Acquire();
170 int v = *value;
171 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 10));
172 *value = v + 1;
173 lock->Release();
174 }
175 v = *value;
176 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 10));
177 *value = v + 1;
178 lock->Release();
179 }
180 }
164 181
165 virtual void ThreadMain() OVERRIDE { 182 virtual void ThreadMain() OVERRIDE {
166 DoStuff(lock_, value_); 183 DoStuff(lock_, value_);
167 } 184 }
168 185
169 private: 186 private:
170 Lock* lock_; 187 RecursiveLock* lock_;
171 int* value_; 188 int* value_;
172 189
173 DISALLOW_COPY_AND_ASSIGN(MutexLockTestThread); 190 DISALLOW_COPY_AND_ASSIGN(MutexRecursiveLockTestThread);
174 }; 191 };
175 192
176 TEST(LockTest, MutexTwoThreads) { 193
177 Lock lock; 194 TEST(RecursiveLockTest, MutexTwoThreadsRecursive) {
195 RecursiveLock lock;
178 int value = 0; 196 int value = 0;
179 197
180 MutexLockTestThread thread(&lock, &value); 198 MutexRecursiveLockTestThread thread(&lock, &value);
181 PlatformThreadHandle handle = kNullThreadHandle; 199 PlatformThreadHandle handle = kNullThreadHandle;
182 200
183 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); 201 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
184 202
185 MutexLockTestThread::DoStuff(&lock, &value); 203 MutexRecursiveLockTestThread::DoStuff(&lock, &value);
186 204
187 PlatformThread::Join(handle); 205 PlatformThread::Join(handle);
188 206
189 EXPECT_EQ(2 * 40, value); 207 EXPECT_EQ(2 * 60, value);
190 } 208 }
191 209
192 TEST(LockTest, MutexFourThreads) { 210 TEST(RecursiveLockTest, MutexFourThreadsRecursive) {
193 Lock lock; 211 RecursiveLock lock;
194 int value = 0; 212 int value = 0;
195 213
196 MutexLockTestThread thread1(&lock, &value); 214 MutexRecursiveLockTestThread thread1(&lock, &value);
197 MutexLockTestThread thread2(&lock, &value); 215 MutexRecursiveLockTestThread thread2(&lock, &value);
198 MutexLockTestThread thread3(&lock, &value); 216 MutexRecursiveLockTestThread thread3(&lock, &value);
199 PlatformThreadHandle handle1 = kNullThreadHandle; 217 PlatformThreadHandle handle1 = kNullThreadHandle;
200 PlatformThreadHandle handle2 = kNullThreadHandle; 218 PlatformThreadHandle handle2 = kNullThreadHandle;
201 PlatformThreadHandle handle3 = kNullThreadHandle; 219 PlatformThreadHandle handle3 = kNullThreadHandle;
202 220
203 ASSERT_TRUE(PlatformThread::Create(0, &thread1, &handle1)); 221 ASSERT_TRUE(PlatformThread::Create(0, &thread1, &handle1));
204 ASSERT_TRUE(PlatformThread::Create(0, &thread2, &handle2)); 222 ASSERT_TRUE(PlatformThread::Create(0, &thread2, &handle2));
205 ASSERT_TRUE(PlatformThread::Create(0, &thread3, &handle3)); 223 ASSERT_TRUE(PlatformThread::Create(0, &thread3, &handle3));
206 224
207 MutexLockTestThread::DoStuff(&lock, &value); 225 MutexRecursiveLockTestThread::DoStuff(&lock, &value);
208 226
209 PlatformThread::Join(handle1); 227 PlatformThread::Join(handle1);
210 PlatformThread::Join(handle2); 228 PlatformThread::Join(handle2);
211 PlatformThread::Join(handle3); 229 PlatformThread::Join(handle3);
212 230
213 EXPECT_EQ(4 * 40, value); 231 EXPECT_EQ(4 * 60, value);
214 } 232 }
215 233
216 } // namespace base 234 } // namespace rlz_lib
OLDNEW
« no previous file with comments | « rlz/lib/recursive_lock.cc ('k') | rlz/rlz.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698