13f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 23345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Use of this source code is governed by a BSD-style license that can be 33345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// found in the LICENSE file. 43345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 53345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <stdlib.h> 63345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 73f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/synchronization/lock.h" 83f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/platform_thread.h" 93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "testing/gtest/include/gtest/gtest.h" 103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsennamespace base { 123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Basic test to make sure that Acquire()/Release()/Try() don't crash ---------- 143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass BasicLockTestThread : public PlatformThread::Delegate { 163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public: 173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick BasicLockTestThread(Lock* lock) : lock_(lock), acquired_(0) {} 183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick virtual void ThreadMain() { 203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (int i = 0; i < 10; i++) { 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick lock_->Acquire(); 223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick acquired_++; 233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick lock_->Release(); 243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (int i = 0; i < 10; i++) { 263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick lock_->Acquire(); 273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick acquired_++; 283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PlatformThread::Sleep(rand() % 20); 293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick lock_->Release(); 303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (int i = 0; i < 10; i++) { 323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (lock_->Try()) { 333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick acquired_++; 343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PlatformThread::Sleep(rand() % 20); 353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick lock_->Release(); 363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int acquired() const { return acquired_; } 413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private: 433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Lock* lock_; 443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int acquired_; 453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DISALLOW_COPY_AND_ASSIGN(BasicLockTestThread); 473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}; 483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 493f50c38dc070f4bb515c1b64450dae14f316474eKristian MonsenTEST(LockTest, Basic) { 503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Lock lock; 513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick BasicLockTestThread thread(&lock); 523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PlatformThreadHandle handle = kNullThreadHandle; 533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); 553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int acquired = 0; 573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (int i = 0; i < 5; i++) { 583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick lock.Acquire(); 593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick acquired++; 603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick lock.Release(); 613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (int i = 0; i < 10; i++) { 633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick lock.Acquire(); 643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick acquired++; 653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PlatformThread::Sleep(rand() % 20); 663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick lock.Release(); 673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (int i = 0; i < 10; i++) { 693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (lock.Try()) { 703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick acquired++; 713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PlatformThread::Sleep(rand() % 20); 723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick lock.Release(); 733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (int i = 0; i < 5; i++) { 763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick lock.Acquire(); 773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick acquired++; 783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PlatformThread::Sleep(rand() % 20); 793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick lock.Release(); 803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PlatformThread::Join(handle); 833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EXPECT_GE(acquired, 20); 853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EXPECT_GE(thread.acquired(), 20); 863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test that Try() works as expected ------------------------------------------- 893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass TryLockTestThread : public PlatformThread::Delegate { 913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public: 923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick TryLockTestThread(Lock* lock) : lock_(lock), got_lock_(false) {} 933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick virtual void ThreadMain() { 953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick got_lock_ = lock_->Try(); 963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (got_lock_) 973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick lock_->Release(); 983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool got_lock() const { return got_lock_; } 1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private: 1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Lock* lock_; 1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool got_lock_; 1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DISALLOW_COPY_AND_ASSIGN(TryLockTestThread); 1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}; 1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1093f50c38dc070f4bb515c1b64450dae14f316474eKristian MonsenTEST(LockTest, TryLock) { 1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Lock lock; 1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_TRUE(lock.Try()); 1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We now have the lock.... 1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // This thread will not be able to get the lock. 1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick { 1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick TryLockTestThread thread(&lock); 1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PlatformThreadHandle handle = kNullThreadHandle; 1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); 1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PlatformThread::Join(handle); 1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_FALSE(thread.got_lock()); 1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick lock.Release(); 1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // This thread will.... 1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick { 1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick TryLockTestThread thread(&lock); 1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PlatformThreadHandle handle = kNullThreadHandle; 1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); 1353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PlatformThread::Join(handle); 1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_TRUE(thread.got_lock()); 1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // But it released it.... 1403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_TRUE(lock.Try()); 1413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick lock.Release(); 1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Tests that locks actually exclude ------------------------------------------- 1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass MutexLockTestThread : public PlatformThread::Delegate { 1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public: 1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick MutexLockTestThread(Lock* lock, int* value) : lock_(lock), value_(value) {} 1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Static helper which can also be called from the main thread. 1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static void DoStuff(Lock* lock, int* value) { 1543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (int i = 0; i < 40; i++) { 1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick lock->Acquire(); 1563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int v = *value; 1573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PlatformThread::Sleep(rand() % 10); 1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *value = v + 1; 1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick lock->Release(); 1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick virtual void ThreadMain() { 1643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DoStuff(lock_, value_); 1653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private: 1683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Lock* lock_; 1693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int* value_; 1703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DISALLOW_COPY_AND_ASSIGN(MutexLockTestThread); 1723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}; 1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1743f50c38dc070f4bb515c1b64450dae14f316474eKristian MonsenTEST(LockTest, MutexTwoThreads) { 1753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Lock lock; 1763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int value = 0; 1773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick MutexLockTestThread thread(&lock, &value); 1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PlatformThreadHandle handle = kNullThreadHandle; 1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); 1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick MutexLockTestThread::DoStuff(&lock, &value); 1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PlatformThread::Join(handle); 1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EXPECT_EQ(2 * 40, value); 1883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1903f50c38dc070f4bb515c1b64450dae14f316474eKristian MonsenTEST(LockTest, MutexFourThreads) { 1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Lock lock; 1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int value = 0; 1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick MutexLockTestThread thread1(&lock, &value); 1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick MutexLockTestThread thread2(&lock, &value); 1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick MutexLockTestThread thread3(&lock, &value); 1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PlatformThreadHandle handle1 = kNullThreadHandle; 1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PlatformThreadHandle handle2 = kNullThreadHandle; 1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PlatformThreadHandle handle3 = kNullThreadHandle; 2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_TRUE(PlatformThread::Create(0, &thread1, &handle1)); 2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_TRUE(PlatformThread::Create(0, &thread2, &handle2)); 2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_TRUE(PlatformThread::Create(0, &thread3, &handle3)); 2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick MutexLockTestThread::DoStuff(&lock, &value); 2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PlatformThread::Join(handle1); 2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PlatformThread::Join(handle2); 2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PlatformThread::Join(handle3); 2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EXPECT_EQ(4 * 40, value); 2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 2143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} // namespace base 215