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);