// 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 #elif defined(OS_POSIX) #include #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_