Commit bbdc8ff8 authored by Robert Liao's avatar Robert Liao Committed by Commit Bot

Remove Read Write Lock

There are no more references to ReadWriteLock in the Chromium codebase.

BUG=758721

Change-Id: I2b83afb9c1682fe349f2e389eb75fc0c368497b6
Reviewed-on: https://chromium-review.googlesource.com/676626Reviewed-by: default avatardanakj <danakj@chromium.org>
Commit-Queue: Robert Liao <robliao@chromium.org>
Cr-Commit-Position: refs/heads/master@{#503618}
parent 92d549f9
......@@ -760,10 +760,6 @@ component("base") {
"synchronization/lock_impl.h",
"synchronization/lock_impl_posix.cc",
"synchronization/lock_impl_win.cc",
"synchronization/read_write_lock.h",
"synchronization/read_write_lock_nacl.cc",
"synchronization/read_write_lock_posix.cc",
"synchronization/read_write_lock_win.cc",
"synchronization/spin_wait.h",
"synchronization/waitable_event.h",
"synchronization/waitable_event_mac.cc",
......@@ -1311,7 +1307,6 @@ component("base") {
"process/process_posix.cc",
"scoped_native_library.cc",
"sync_socket_posix.cc",
"synchronization/read_write_lock_posix.cc",
"sys_info.cc",
"sys_info_posix.cc",
"task_scheduler/initialization_util.cc",
......@@ -1352,7 +1347,6 @@ component("base") {
"os_compat_nacl.cc",
"os_compat_nacl.h",
"rand_util_nacl.cc",
"synchronization/read_write_lock_nacl.cc",
]
if (use_partition_alloc) {
......@@ -2145,7 +2139,6 @@ test("base_unittests") {
"synchronization/atomic_flag_unittest.cc",
"synchronization/condition_variable_unittest.cc",
"synchronization/lock_unittest.cc",
"synchronization/read_write_lock_unittest.cc",
"synchronization/waitable_event_unittest.cc",
"synchronization/waitable_event_watcher_unittest.cc",
"sys_byteorder_unittest.cc",
......
// 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.
#ifndef BASE_SYNCHRONIZATION_READ_WRITE_LOCK_H_
#define BASE_SYNCHRONIZATION_READ_WRITE_LOCK_H_
#include "base/base_export.h"
#include "base/macros.h"
#include "build/build_config.h"
#if defined(OS_NACL)
#include "base/synchronization/lock.h"
#endif
#if defined(OS_WIN)
#include <windows.h>
#elif defined(OS_POSIX)
#include <pthread.h>
#else
# error No reader-writer lock defined for this platform.
#endif
namespace base {
namespace subtle {
// An OS-independent wrapper around reader-writer locks. There's no magic here.
//
// You are strongly encouraged to use base::Lock instead of this, unless you
// can demonstrate contention and show that this would lead to an improvement.
// This lock does not make any guarantees of fairness, which can lead to writer
// starvation under certain access patterns. You should carefully consider your
// writer access patterns before using this lock.
class BASE_EXPORT ReadWriteLock {
public:
ReadWriteLock();
~ReadWriteLock();
// Reader lock functions.
void ReadAcquire();
void ReadRelease();
// Writer lock functions.
void WriteAcquire();
void WriteRelease();
private:
#if defined(OS_WIN)
using NativeHandle = SRWLOCK;
#elif defined(OS_NACL)
using NativeHandle = Lock;
#elif defined(OS_POSIX)
using NativeHandle = pthread_rwlock_t;
#endif
NativeHandle native_handle_;
#if defined(OS_NACL)
// Even though NaCl has a pthread_rwlock implementation, the build rules don't
// make it universally available. So instead, implement a slower and trivial
// reader-writer lock using a regular mutex.
// TODO(amistry): Remove this and use the posix implementation when it's
// available in all build configurations.
uint32_t readers_ = 0;
// base::Lock does checking to ensure the lock is acquired and released on the
// same thread. This is not the case for this lock, so use pthread mutexes
// directly here.
pthread_mutex_t writer_lock_ = PTHREAD_MUTEX_INITIALIZER;
#endif
DISALLOW_COPY_AND_ASSIGN(ReadWriteLock);
};
class AutoReadLock {
public:
explicit AutoReadLock(ReadWriteLock& lock) : lock_(lock) {
lock_.ReadAcquire();
}
~AutoReadLock() {
lock_.ReadRelease();
}
private:
ReadWriteLock& lock_;
DISALLOW_COPY_AND_ASSIGN(AutoReadLock);
};
class AutoWriteLock {
public:
explicit AutoWriteLock(ReadWriteLock& lock) : lock_(lock) {
lock_.WriteAcquire();
}
~AutoWriteLock() {
lock_.WriteRelease();
}
private:
ReadWriteLock& lock_;
DISALLOW_COPY_AND_ASSIGN(AutoWriteLock);
};
} // namespace subtle
} // namespace base
#endif // BASE_SYNCHRONIZATION_READ_WRITE_LOCK_H_
// 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/read_write_lock.h"
#include "base/logging.h"
namespace base {
namespace subtle {
ReadWriteLock::ReadWriteLock() {}
ReadWriteLock::~ReadWriteLock() {
DCHECK_EQ(0u, readers_);
int result = pthread_mutex_destroy(&writer_lock_);
DCHECK_EQ(result, 0) << ". " << strerror(result);
}
void ReadWriteLock::ReadAcquire() {
AutoLock hold(native_handle_);
readers_++;
if (readers_ == 1) {
int result = pthread_mutex_lock(&writer_lock_);
DCHECK_EQ(result, 0) << ". " << strerror(result);
}
}
void ReadWriteLock::ReadRelease() {
AutoLock hold(native_handle_);
readers_--;
if (readers_ == 0) {
int result = pthread_mutex_unlock(&writer_lock_);
DCHECK_EQ(result, 0) << ". " << strerror(result);
}
}
void ReadWriteLock::WriteAcquire() {
int result = pthread_mutex_lock(&writer_lock_);
DCHECK_EQ(result, 0) << ". " << strerror(result);
}
void ReadWriteLock::WriteRelease() {
int result = pthread_mutex_unlock(&writer_lock_);
DCHECK_EQ(result, 0) << ". " << strerror(result);
}
} // namespace subtle
} // namespace base
// 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/read_write_lock.h"
#include "base/logging.h"
namespace base {
namespace subtle {
ReadWriteLock::ReadWriteLock() : native_handle_(PTHREAD_RWLOCK_INITIALIZER) {}
ReadWriteLock::~ReadWriteLock() {
int result = pthread_rwlock_destroy(&native_handle_);
DCHECK_EQ(result, 0) << ". " << strerror(result);
}
void ReadWriteLock::ReadAcquire() {
int result = pthread_rwlock_rdlock(&native_handle_);
DCHECK_EQ(result, 0) << ". " << strerror(result);
}
void ReadWriteLock::ReadRelease() {
int result = pthread_rwlock_unlock(&native_handle_);
DCHECK_EQ(result, 0) << ". " << strerror(result);
}
void ReadWriteLock::WriteAcquire() {
int result = pthread_rwlock_wrlock(&native_handle_);
DCHECK_EQ(result, 0) << ". " << strerror(result);
}
void ReadWriteLock::WriteRelease() {
int result = pthread_rwlock_unlock(&native_handle_);
DCHECK_EQ(result, 0) << ". " << strerror(result);
}
} // namespace subtle
} // namespace base
// 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/read_write_lock.h"
#include <stdlib.h>
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
namespace subtle {
// Basic test to make sure that *Acquire()/*Release() don't crash.
class BasicReadWriteLockTestThread : public PlatformThread::Delegate {
public:
explicit BasicReadWriteLockTestThread(ReadWriteLock* lock)
: lock_(lock), acquired_(0) {}
void ThreadMain() override {
for (int i = 0; i < 10; i++) {
AutoReadLock locker(*lock_);
acquired_++;
}
for (int i = 0; i < 10; i++) {
AutoWriteLock locker(*lock_);
acquired_++;
PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
}
}
int acquired() const { return acquired_; }
private:
ReadWriteLock* lock_;
int acquired_;
DISALLOW_COPY_AND_ASSIGN(BasicReadWriteLockTestThread);
};
TEST(ReadWriteLockTest, Basic) {
ReadWriteLock lock;
BasicReadWriteLockTestThread thread(&lock);
PlatformThreadHandle handle;
ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
int acquired = 0;
for (int i = 0; i < 5; i++) {
AutoReadLock locker(lock);
acquired++;
}
for (int i = 0; i < 10; i++) {
AutoWriteLock locker(lock);
acquired++;
PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
}
for (int i = 0; i < 5; i++) {
AutoReadLock locker(lock);
acquired++;
}
PlatformThread::Join(handle);
EXPECT_EQ(20, acquired);
EXPECT_GE(20, thread.acquired());
}
// Tests that reader locks allow multiple simultaneous reader acquisitions.
class ReaderReadWriteLockTestThread : public PlatformThread::Delegate {
public:
ReaderReadWriteLockTestThread(ReadWriteLock* lock) : lock_(lock) {}
void ThreadMain() override {
AutoReadLock locker(*lock_);
did_acquire_ = true;
}
bool did_acquire() const { return did_acquire_; }
private:
ReadWriteLock* lock_;
bool did_acquire_ = false;
DISALLOW_COPY_AND_ASSIGN(ReaderReadWriteLockTestThread);
};
TEST(ReadWriteLockTest, ReaderTwoThreads) {
ReadWriteLock lock;
AutoReadLock auto_lock(lock);
ReaderReadWriteLockTestThread thread(&lock);
PlatformThreadHandle handle;
ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
PlatformThread::Join(handle);
EXPECT_TRUE(thread.did_acquire());
}
// Tests that writer locks exclude reader locks.
class ReadAndWriteReadWriteLockTestThread : public PlatformThread::Delegate {
public:
ReadAndWriteReadWriteLockTestThread(ReadWriteLock* lock, int* value)
: lock_(lock),
value_(value),
event_(WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED) {}
void ThreadMain() override {
AutoWriteLock locker(*lock_);
(*value_)++;
event_.Signal();
}
void Wait() {
event_.Wait();
}
private:
ReadWriteLock* lock_;
int* value_;
WaitableEvent event_;
DISALLOW_COPY_AND_ASSIGN(ReadAndWriteReadWriteLockTestThread);
};
TEST(ReadWriteLockTest, ReadAndWriteThreads) {
ReadWriteLock lock;
int value = 0;
ReadAndWriteReadWriteLockTestThread thread(&lock, &value);
PlatformThreadHandle handle;
{
AutoReadLock read_locker(lock);
ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
PlatformThread::Sleep(TimeDelta::FromMilliseconds(10));
// |value| should be unchanged since we hold a reader lock.
EXPECT_EQ(0, value);
}
thread.Wait();
// After releasing our reader lock, the thread can acquire a write lock and
// change |value|.
EXPECT_EQ(1, value);
PlatformThread::Join(handle);
}
// Tests that writer locks actually exclude.
class WriterReadWriteLockTestThread : public PlatformThread::Delegate {
public:
WriterReadWriteLockTestThread(ReadWriteLock* lock, int* value)
: lock_(lock), value_(value) {}
// Static helper which can also be called from the main thread.
static void DoStuff(ReadWriteLock* lock, int* value) {
for (int i = 0; i < 40; i++) {
AutoWriteLock locker(*lock);
int v = *value;
PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 10));
*value = v + 1;
}
}
void ThreadMain() override { DoStuff(lock_, value_); }
private:
ReadWriteLock* lock_;
int* value_;
DISALLOW_COPY_AND_ASSIGN(WriterReadWriteLockTestThread);
};
TEST(ReadWriteLockTest, MutexTwoThreads) {
ReadWriteLock lock;
int value = 0;
WriterReadWriteLockTestThread thread(&lock, &value);
PlatformThreadHandle handle;
ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
WriterReadWriteLockTestThread::DoStuff(&lock, &value);
PlatformThread::Join(handle);
EXPECT_EQ(2 * 40, value);
}
TEST(ReadWriteLockTest, MutexFourThreads) {
ReadWriteLock lock;
int value = 0;
WriterReadWriteLockTestThread thread1(&lock, &value);
WriterReadWriteLockTestThread thread2(&lock, &value);
WriterReadWriteLockTestThread 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));
WriterReadWriteLockTestThread::DoStuff(&lock, &value);
PlatformThread::Join(handle1);
PlatformThread::Join(handle2);
PlatformThread::Join(handle3);
EXPECT_EQ(4 * 40, value);
}
} // namespace subtle
} // namespace base
// 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/read_write_lock.h"
namespace base {
namespace subtle {
ReadWriteLock::ReadWriteLock() : native_handle_(SRWLOCK_INIT) {}
ReadWriteLock::~ReadWriteLock() = default;
void ReadWriteLock::ReadAcquire() {
::AcquireSRWLockShared(&native_handle_);
}
void ReadWriteLock::ReadRelease() {
::ReleaseSRWLockShared(&native_handle_);
}
void ReadWriteLock::WriteAcquire() {
::AcquireSRWLockExclusive(&native_handle_);
}
void ReadWriteLock::WriteRelease() {
::ReleaseSRWLockExclusive(&native_handle_);
}
} // namespace subtle
} // namespace base
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment