Chromium Code Reviews| Index: base/synchronization/rw_lock_unittest.cc |
| diff --git a/base/synchronization/rw_lock_unittest.cc b/base/synchronization/rw_lock_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..7097355b1a3088606ca850e0f6dc46d88a5424ce |
| --- /dev/null |
| +++ b/base/synchronization/rw_lock_unittest.cc |
| @@ -0,0 +1,177 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "base/synchronization/rw_lock.h" |
| + |
| +#include <stdlib.h> |
| + |
| +#include "base/compiler_specific.h" |
| +#include "base/macros.h" |
| +#include "base/threading/platform_thread.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +namespace base { |
| + |
| +// Basic test to make sure that *Acquire()/*Release() don't crash ---------- |
|
danakj
2016/05/19 23:01:37
replace the " ----------" with "." and ditto elsew
Anand Mistry (off Chromium)
2016/05/20 04:06:39
Done.
|
| + |
| +class BasicRWLockTestThread : public PlatformThread::Delegate { |
| + public: |
| + explicit BasicRWLockTestThread(RWLock* lock) : lock_(lock), acquired_(0) {} |
| + |
| + void ThreadMain() override { |
| + for (int i = 0; i < 10; i++) { |
| + lock_->ReadAcquire(); |
| + acquired_++; |
| + lock_->ReadRelease(); |
| + } |
| + for (int i = 0; i < 10; i++) { |
| + lock_->WriteAcquire(); |
| + acquired_++; |
| + PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20)); |
| + lock_->WriteRelease(); |
| + } |
| + } |
| + |
| + int acquired() const { return acquired_; } |
| + |
| + private: |
| + RWLock* lock_; |
| + int acquired_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(BasicRWLockTestThread); |
| +}; |
| + |
| +TEST(RWLockTest, Basic) { |
| + RWLock lock; |
| + BasicRWLockTestThread thread(&lock); |
| + PlatformThreadHandle handle; |
| + |
| + ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); |
| + |
| + int acquired = 0; |
| + for (int i = 0; i < 5; i++) { |
|
danakj
2016/05/19 23:01:37
I don't really get the point of this test. What is
Anand Mistry (off Chromium)
2016/05/20 04:06:39
It's a basic sanity test to ensure that acquisitio
|
| + lock.ReadAcquire(); |
| + acquired++; |
| + lock.ReadRelease(); |
| + } |
| + for (int i = 0; i < 10; i++) { |
| + lock.WriteAcquire(); |
| + acquired++; |
| + PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20)); |
| + lock.WriteRelease(); |
| + } |
| + for (int i = 0; i < 5; i++) { |
| + lock.ReadAcquire(); |
| + acquired++; |
| + lock.ReadRelease(); |
| + } |
| + |
| + PlatformThread::Join(handle); |
| + |
| + EXPECT_EQ(20, acquired); |
| + EXPECT_GE(20, thread.acquired()); |
| +} |
| + |
| +// Tests that reader locks allow multiple simultaneous acquisitions --------- |
| + |
| +class ReaderRWLockTestThread : public PlatformThread::Delegate { |
| + public: |
| + ReaderRWLockTestThread(RWLock* lock) : lock_(lock) {} |
| + |
| + void ThreadMain() override { |
| + lock_->ReadAcquire(); |
|
danakj
2016/05/19 23:01:37
Use AutoReadLock
Anand Mistry (off Chromium)
2016/05/20 04:06:39
Done.
|
| + did_acquire_ = true; |
| + lock_->ReadRelease(); |
| + } |
| + |
| + bool did_acquire() const { return did_acquire_; } |
| + |
| + private: |
| + RWLock* lock_; |
| + bool did_acquire_ = false; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(ReaderRWLockTestThread); |
| +}; |
| + |
| +TEST(RWLockTest, ReaderTwoThreads) { |
| + RWLock lock; |
| + |
| + AutoReadLock auto_lock(lock); |
| + |
| + ReaderRWLockTestThread thread(&lock); |
| + PlatformThreadHandle handle; |
| + |
| + ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); |
| + PlatformThread::Join(handle); |
| + EXPECT_TRUE(thread.did_acquire()); |
| +} |
| + |
| +// Tests that writer locks actually exclude --------------------------------- |
| + |
| +class WriterRWLockTestThread : public PlatformThread::Delegate { |
| + public: |
| + WriterRWLockTestThread(RWLock* lock, int* value) |
| + : lock_(lock), value_(value) {} |
| + |
| + // Static helper which can also be called from the main thread. |
| + static void DoStuff(RWLock* lock, int* value) { |
| + for (int i = 0; i < 40; i++) { |
| + lock->WriteAcquire(); |
| + int v = *value; |
| + PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 10)); |
| + *value = v + 1; |
| + lock->WriteRelease(); |
| + } |
| + } |
| + |
| + void ThreadMain() override { DoStuff(lock_, value_); } |
| + |
| + private: |
| + RWLock* lock_; |
| + int* value_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(WriterRWLockTestThread); |
| +}; |
| + |
| +TEST(RWLockTest, MutexTwoThreads) { |
| + RWLock lock; |
| + int value = 0; |
| + |
| + WriterRWLockTestThread thread(&lock, &value); |
| + PlatformThreadHandle handle; |
| + |
| + ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); |
| + |
| + WriterRWLockTestThread::DoStuff(&lock, &value); |
|
danakj
2016/05/19 23:01:37
This seems like you could write a bit more obvious
Anand Mistry (off Chromium)
2016/05/20 04:06:38
Done.
|
| + |
| + PlatformThread::Join(handle); |
| + |
| + EXPECT_EQ(2 * 40, value); |
| +} |
| + |
| +TEST(RWLockTest, MutexFourThreads) { |
| + RWLock lock; |
| + int value = 0; |
| + |
| + WriterRWLockTestThread thread1(&lock, &value); |
| + WriterRWLockTestThread thread2(&lock, &value); |
| + WriterRWLockTestThread thread3(&lock, &value); |
| + PlatformThreadHandle handle1; |
| + PlatformThreadHandle handle2; |
| + PlatformThreadHandle handle3; |
| + |
| + ASSERT_TRUE(PlatformThread::Create(0, &thread1, &handle1)); |
| + ASSERT_TRUE(PlatformThread::Create(0, &thread2, &handle2)); |
| + ASSERT_TRUE(PlatformThread::Create(0, &thread3, &handle3)); |
| + |
| + WriterRWLockTestThread::DoStuff(&lock, &value); |
| + |
| + PlatformThread::Join(handle1); |
| + PlatformThread::Join(handle2); |
| + PlatformThread::Join(handle3); |
| + |
| + EXPECT_EQ(4 * 40, value); |
| +} |
| + |
| +} // namespace base |