lock_impl.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // Copyright (c) 2011 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_SYNCHRONIZATION_LOCK_IMPL_H_
  5. #define BASE_SYNCHRONIZATION_LOCK_IMPL_H_
  6. #include "base/base_export.h"
  7. #include "base/logging.h"
  8. #include "base/macros.h"
  9. #include "base/thread_annotations.h"
  10. #include "build/build_config.h"
  11. #if defined(OS_WIN)
  12. #include "base/win/windows_types.h"
  13. #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
  14. #include <errno.h>
  15. #include <pthread.h>
  16. #include <string.h>
  17. #include <ostream>
  18. #endif
  19. namespace base {
  20. namespace internal {
  21. // This class implements the underlying platform-specific spin-lock mechanism
  22. // used for the Lock class. Most users should not use LockImpl directly, but
  23. // should instead use Lock.
  24. class BASE_EXPORT LockImpl {
  25. public:
  26. #if defined(OS_WIN)
  27. using NativeHandle = CHROME_SRWLOCK;
  28. #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
  29. using NativeHandle = pthread_mutex_t;
  30. #endif
  31. LockImpl();
  32. ~LockImpl();
  33. // If the lock is not held, take it and return true. If the lock is already
  34. // held by something else, immediately return false.
  35. bool Try();
  36. // Take the lock, blocking until it is available if necessary.
  37. void Lock();
  38. // Release the lock. This must only be called by the lock's holder: after
  39. // a successful call to Try, or a call to Lock.
  40. inline void Unlock();
  41. // Return the native underlying lock.
  42. // TODO(awalker): refactor lock and condition variables so that this is
  43. // unnecessary.
  44. NativeHandle* native_handle() { return &native_handle_; }
  45. #if defined(OS_POSIX) || defined(OS_FUCHSIA)
  46. // Whether this lock will attempt to use priority inheritance.
  47. static bool PriorityInheritanceAvailable();
  48. #endif
  49. private:
  50. NativeHandle native_handle_;
  51. DISALLOW_COPY_AND_ASSIGN(LockImpl);
  52. };
  53. #if defined(OS_WIN)
  54. void LockImpl::Unlock() {
  55. ::ReleaseSRWLockExclusive(reinterpret_cast<PSRWLOCK>(&native_handle_));
  56. }
  57. #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
  58. void LockImpl::Unlock() {
  59. int rv = pthread_mutex_unlock(&native_handle_);
  60. DCHECK_EQ(rv, 0) << ". " << strerror(rv);
  61. }
  62. #endif
  63. // This is an implementation used for AutoLock templated on the lock type.
  64. template <class LockType>
  65. class SCOPED_LOCKABLE BasicAutoLock {
  66. public:
  67. struct AlreadyAcquired {};
  68. explicit BasicAutoLock(LockType& lock) EXCLUSIVE_LOCK_FUNCTION(lock)
  69. : lock_(lock) {
  70. lock_.Acquire();
  71. }
  72. BasicAutoLock(LockType& lock, const AlreadyAcquired&)
  73. EXCLUSIVE_LOCKS_REQUIRED(lock)
  74. : lock_(lock) {
  75. lock_.AssertAcquired();
  76. }
  77. ~BasicAutoLock() UNLOCK_FUNCTION() {
  78. lock_.AssertAcquired();
  79. lock_.Release();
  80. }
  81. private:
  82. LockType& lock_;
  83. DISALLOW_COPY_AND_ASSIGN(BasicAutoLock);
  84. };
  85. // This is an implementation used for AutoUnlock templated on the lock type.
  86. template <class LockType>
  87. class BasicAutoUnlock {
  88. public:
  89. explicit BasicAutoUnlock(LockType& lock) : lock_(lock) {
  90. // We require our caller to have the lock.
  91. lock_.AssertAcquired();
  92. lock_.Release();
  93. }
  94. ~BasicAutoUnlock() { lock_.Acquire(); }
  95. private:
  96. LockType& lock_;
  97. DISALLOW_COPY_AND_ASSIGN(BasicAutoUnlock);
  98. };
  99. // This is an implementation used for AutoLockMaybe templated on the lock type.
  100. template <class LockType>
  101. class SCOPED_LOCKABLE BasicAutoLockMaybe {
  102. public:
  103. explicit BasicAutoLockMaybe(LockType* lock) EXCLUSIVE_LOCK_FUNCTION(lock)
  104. : lock_(lock) {
  105. if (lock_)
  106. lock_->Acquire();
  107. }
  108. ~BasicAutoLockMaybe() UNLOCK_FUNCTION() {
  109. if (lock_) {
  110. lock_->AssertAcquired();
  111. lock_->Release();
  112. }
  113. }
  114. private:
  115. LockType* const lock_;
  116. DISALLOW_COPY_AND_ASSIGN(BasicAutoLockMaybe);
  117. };
  118. // This is an implementation used for ReleasableAutoLock templated on the lock
  119. // type.
  120. template <class LockType>
  121. class SCOPED_LOCKABLE BasicReleasableAutoLock {
  122. public:
  123. explicit BasicReleasableAutoLock(LockType* lock) EXCLUSIVE_LOCK_FUNCTION(lock)
  124. : lock_(lock) {
  125. DCHECK(lock_);
  126. lock_->Acquire();
  127. }
  128. ~BasicReleasableAutoLock() UNLOCK_FUNCTION() {
  129. if (lock_) {
  130. lock_->AssertAcquired();
  131. lock_->Release();
  132. }
  133. }
  134. void Release() UNLOCK_FUNCTION() {
  135. DCHECK(lock_);
  136. lock_->AssertAcquired();
  137. lock_->Release();
  138. lock_ = nullptr;
  139. }
  140. private:
  141. LockType* lock_;
  142. DISALLOW_COPY_AND_ASSIGN(BasicReleasableAutoLock);
  143. };
  144. } // namespace internal
  145. } // namespace base
  146. #endif // BASE_SYNCHRONIZATION_LOCK_IMPL_H_