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
3 // found in the LICENSE file.
5 #include "base/synchronization/lock.h"
9 #include "base/compiler_specific.h"
10 #include "base/threading/platform_thread.h"
11 #include "testing/gtest/include/gtest/gtest.h"
15 // Basic test to make sure that Acquire()/Release()/Try() don't crash ----------
17 class BasicLockTestThread
: public PlatformThread::Delegate
{
19 explicit BasicLockTestThread(Lock
* lock
) : lock_(lock
), acquired_(0) {}
21 void ThreadMain() override
{
22 for (int i
= 0; i
< 10; i
++) {
27 for (int i
= 0; i
< 10; i
++) {
30 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
33 for (int i
= 0; i
< 10; i
++) {
36 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
42 int acquired() const { return acquired_
; }
48 DISALLOW_COPY_AND_ASSIGN(BasicLockTestThread
);
51 TEST(LockTest
, Basic
) {
53 BasicLockTestThread
thread(&lock
);
54 PlatformThreadHandle handle
;
56 ASSERT_TRUE(PlatformThread::Create(0, &thread
, &handle
));
59 for (int i
= 0; i
< 5; i
++) {
64 for (int i
= 0; i
< 10; i
++) {
67 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
70 for (int i
= 0; i
< 10; i
++) {
73 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
77 for (int i
= 0; i
< 5; i
++) {
80 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
84 PlatformThread::Join(handle
);
86 EXPECT_GE(acquired
, 20);
87 EXPECT_GE(thread
.acquired(), 20);
90 // Test that Try() works as expected -------------------------------------------
92 class TryLockTestThread
: public PlatformThread::Delegate
{
94 explicit TryLockTestThread(Lock
* lock
) : lock_(lock
), got_lock_(false) {}
96 void ThreadMain() override
{
97 got_lock_
= lock_
->Try();
102 bool got_lock() const { return got_lock_
; }
108 DISALLOW_COPY_AND_ASSIGN(TryLockTestThread
);
111 TEST(LockTest
, TryLock
) {
114 ASSERT_TRUE(lock
.Try());
115 // We now have the lock....
117 // This thread will not be able to get the lock.
119 TryLockTestThread
thread(&lock
);
120 PlatformThreadHandle handle
;
122 ASSERT_TRUE(PlatformThread::Create(0, &thread
, &handle
));
124 PlatformThread::Join(handle
);
126 ASSERT_FALSE(thread
.got_lock());
131 // This thread will....
133 TryLockTestThread
thread(&lock
);
134 PlatformThreadHandle handle
;
136 ASSERT_TRUE(PlatformThread::Create(0, &thread
, &handle
));
138 PlatformThread::Join(handle
);
140 ASSERT_TRUE(thread
.got_lock());
141 // But it released it....
142 ASSERT_TRUE(lock
.Try());
148 // Tests that locks actually exclude -------------------------------------------
150 class MutexLockTestThread
: public PlatformThread::Delegate
{
152 MutexLockTestThread(Lock
* lock
, int* value
) : lock_(lock
), value_(value
) {}
154 // Static helper which can also be called from the main thread.
155 static void DoStuff(Lock
* lock
, int* value
) {
156 for (int i
= 0; i
< 40; i
++) {
159 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 10));
165 void ThreadMain() override
{ DoStuff(lock_
, value_
); }
171 DISALLOW_COPY_AND_ASSIGN(MutexLockTestThread
);
174 TEST(LockTest
, MutexTwoThreads
) {
178 MutexLockTestThread
thread(&lock
, &value
);
179 PlatformThreadHandle handle
;
181 ASSERT_TRUE(PlatformThread::Create(0, &thread
, &handle
));
183 MutexLockTestThread::DoStuff(&lock
, &value
);
185 PlatformThread::Join(handle
);
187 EXPECT_EQ(2 * 40, value
);
190 TEST(LockTest
, MutexFourThreads
) {
194 MutexLockTestThread
thread1(&lock
, &value
);
195 MutexLockTestThread
thread2(&lock
, &value
);
196 MutexLockTestThread
thread3(&lock
, &value
);
197 PlatformThreadHandle handle1
;
198 PlatformThreadHandle handle2
;
199 PlatformThreadHandle handle3
;
201 ASSERT_TRUE(PlatformThread::Create(0, &thread1
, &handle1
));
202 ASSERT_TRUE(PlatformThread::Create(0, &thread2
, &handle2
));
203 ASSERT_TRUE(PlatformThread::Create(0, &thread3
, &handle3
));
205 MutexLockTestThread::DoStuff(&lock
, &value
);
207 PlatformThread::Join(handle1
);
208 PlatformThread::Join(handle2
);
209 PlatformThread::Join(handle3
);
211 EXPECT_EQ(4 * 40, value
);