15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "mojo/public/cpp/utility/mutex.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <stdlib.h> // For |rand()|. 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <time.h> // For |nanosleep()| (defined by POSIX). 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <vector> 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 12effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "mojo/public/cpp/system/macros.h" 13effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "mojo/public/cpp/utility/thread.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace mojo { 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(MutexTest, TrivialSingleThreaded) { 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Mutex mutex; 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mutex.Lock(); 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mutex.AssertHeld(); 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mutex.Unlock(); 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(mutex.TryLock()); 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mutex.AssertHeld(); 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mutex.Unlock(); 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) { 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MutexLock lock(&mutex); 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mutex.AssertHeld(); 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(mutex.TryLock()); 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mutex.Unlock(); 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class Fiddler { 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enum Type { kTypeLock, kTypeTry }; 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Fiddler(size_t times_to_lock, 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Type type, 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool should_sleep, 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Mutex* mutex, 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int* shared_value) 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : times_to_lock_(times_to_lock), 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) type_(type), 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) should_sleep_(should_sleep), 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mutex_(mutex), 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) shared_value_(shared_value) { 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ~Fiddler() { 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void Fiddle() { 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (size_t i = 0; i < times_to_lock_;) { 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) switch (type_) { 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case kTypeLock: { 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mutex_->Lock(); 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int old_shared_value = *shared_value_; 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (should_sleep_) 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SleepALittle(); 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *shared_value_ = old_shared_value + 1; 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mutex_->Unlock(); 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) i++; 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case kTypeTry: 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (mutex_->TryLock()) { 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int old_shared_value = *shared_value_; 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (should_sleep_) 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SleepALittle(); 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *shared_value_ = old_shared_value + 1; 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mutex_->Unlock(); 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) i++; 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SleepALittle(); // Don't spin. 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static void SleepALittle() { 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const long kNanosPerMilli = 1000000; 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) struct timespec req = { 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 0, // Seconds. 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (rand() % 10) * kNanosPerMilli // Nanoseconds. 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }; 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int rv MOJO_ALLOW_UNUSED = nanosleep(&req, NULL); 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) assert(rv == 0); 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const size_t times_to_lock_; 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const Type type_; 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const bool should_sleep_; 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Mutex* const mutex_; 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int* const shared_value_; 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MOJO_DISALLOW_COPY_AND_ASSIGN(Fiddler); 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class FiddlerThread : public Thread { 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Takes ownership of |fiddler|. 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FiddlerThread(Fiddler* fiddler) 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : fiddler_(fiddler) { 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ~FiddlerThread() { 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delete fiddler_; 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void Run() MOJO_OVERRIDE { 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) fiddler_->Fiddle(); 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Fiddler* const fiddler_; 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MOJO_DISALLOW_COPY_AND_ASSIGN(FiddlerThread); 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This does a stress test (that also checks exclusion). 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(MutexTest, ThreadedStress) { 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const size_t kNumThreads = 20; 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const int kTimesToLockEach = 20; 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) assert(kNumThreads % 4 == 0); 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Mutex mutex; 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int shared_value = 0; 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<FiddlerThread*> fiddler_threads; 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (size_t i = 0; i < kNumThreads; i += 4) { 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) fiddler_threads.push_back(new FiddlerThread(new Fiddler( 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kTimesToLockEach, Fiddler::kTypeLock, false, &mutex, &shared_value))); 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) fiddler_threads.push_back(new FiddlerThread(new Fiddler( 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kTimesToLockEach, Fiddler::kTypeTry, false, &mutex, &shared_value))); 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) fiddler_threads.push_back(new FiddlerThread(new Fiddler( 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kTimesToLockEach, Fiddler::kTypeLock, true, &mutex, &shared_value))); 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) fiddler_threads.push_back(new FiddlerThread(new Fiddler( 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kTimesToLockEach, Fiddler::kTypeTry, true, &mutex, &shared_value))); 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (size_t i = 0; i < kNumThreads; i++) 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) fiddler_threads[i]->Start(); 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Do some fiddling ourselves. 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Fiddler(kTimesToLockEach, Fiddler::kTypeLock, true, &mutex, &shared_value) 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .Fiddle(); 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Join. 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (size_t i = 0; i < kNumThreads; i++) 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) fiddler_threads[i]->Join(); 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(static_cast<int>(kNumThreads + 1) * kTimesToLockEach, shared_value); 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Delete. 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (size_t i = 0; i < kNumThreads; i++) 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delete fiddler_threads[i]; 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) fiddler_threads.clear(); 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class TryThread : public Thread { 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) explicit TryThread(Mutex* mutex) : mutex_(mutex), try_lock_succeeded_() {} 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ~TryThread() {} 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void Run() MOJO_OVERRIDE { 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) try_lock_succeeded_ = mutex_->TryLock(); 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (try_lock_succeeded_) 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mutex_->Unlock(); 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool try_lock_succeeded() const { return try_lock_succeeded_; } 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Mutex* const mutex_; 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool try_lock_succeeded_; 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MOJO_DISALLOW_COPY_AND_ASSIGN(TryThread); 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(MutexTest, TryLock) { 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Mutex mutex; 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // |TryLock()| should succeed -- we don't have the lock. 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) { 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) TryThread thread(&mutex); 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) thread.Start(); 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) thread.Join(); 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(thread.try_lock_succeeded()); 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Take the lock. 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(mutex.TryLock()); 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Now it should fail. 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) { 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) TryThread thread(&mutex); 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) thread.Start(); 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) thread.Join(); 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(thread.try_lock_succeeded()); 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Release the lock. 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mutex.Unlock(); 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // It should succeed again. 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) { 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) TryThread thread(&mutex); 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) thread.Start(); 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) thread.Join(); 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(thread.try_lock_succeeded()); 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Tests of assertions for Debug builds. 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if !defined(NDEBUG) 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Test |AssertHeld()| (which is an actual user API). 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(MutexTest, DebugAssertHeldFailure) { 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Mutex mutex; 2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_DEATH_IF_SUPPORTED(mutex.AssertHeld(), ""); 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Test other consistency checks. 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(MutexTest, DebugAssertionFailures) { 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Unlock without lock held. 2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_DEATH_IF_SUPPORTED({ 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Mutex mutex; 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mutex.Unlock(); 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }, ""); 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Lock with lock held (on same thread). 2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_DEATH_IF_SUPPORTED({ 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Mutex mutex; 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mutex.Lock(); 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mutex.Lock(); 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }, ""); 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Try lock with lock held. 2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_DEATH_IF_SUPPORTED({ 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Mutex mutex; 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mutex.Lock(); 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mutex.TryLock(); 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }, ""); 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Destroy lock with lock held. 2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_DEATH_IF_SUPPORTED({ 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Mutex mutex; 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mutex.Lock(); 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }, ""); 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif // !defined(NDEBUG) 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace mojo 263