blob: d9cfbb758f13ae5ceca13deb7bb19774d2b92618 [file] [log] [blame]
[email protected]bc581a682011-01-01 23:16:201// 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
5#ifndef BASE_SYNCHRONIZATION_LOCK_H_
6#define BASE_SYNCHRONIZATION_LOCK_H_
[email protected]bc581a682011-01-01 23:16:207
[email protected]0bea7252011-08-05 15:34:008#include "base/base_export.h"
Hans Wennborg7b533712020-06-22 20:52:279#include "base/check_op.h"
avi9b6f42932015-12-26 22:15:1410#include "base/macros.h"
[email protected]bc581a682011-01-01 23:16:2011#include "base/synchronization/lock_impl.h"
Lukasz Anforowicz5e71bd42018-09-17 19:28:5712#include "base/thread_annotations.h"
[email protected]bc581a682011-01-01 23:16:2013#include "base/threading/platform_thread.h"
avi9b6f42932015-12-26 22:15:1414#include "build/build_config.h"
[email protected]bc581a682011-01-01 23:16:2015
16namespace base {
17
18// A convenient wrapper for an OS specific critical section. The only real
19// intelligence in this class is in debug mode for the support for the
20// AssertAcquired() method.
Lukasz Anforowicz5e71bd42018-09-17 19:28:5721class LOCKABLE BASE_EXPORT Lock {
[email protected]bc581a682011-01-01 23:16:2022 public:
olli.raula7e1b45842015-09-11 13:06:1023#if !DCHECK_IS_ON()
Lukasz Anforowicz5e71bd42018-09-17 19:28:5724 // Optimized wrapper implementation
[email protected]32f3c232014-02-24 02:09:2925 Lock() : lock_() {}
26 ~Lock() {}
Lukasz Anforowicz5e71bd42018-09-17 19:28:5727
Benoît Lizéa38dbf5d2020-03-11 08:33:5828 void Acquire() EXCLUSIVE_LOCK_FUNCTION() { lock_.Lock(); }
29 void Release() UNLOCK_FUNCTION() { lock_.Unlock(); }
[email protected]32f3c232014-02-24 02:09:2930
31 // If the lock is not held, take it and return true. If the lock is already
32 // held by another thread, immediately return false. This must not be called
33 // by a thread already holding the lock (what happens is undefined and an
34 // assertion may fail).
Benoît Lizéa38dbf5d2020-03-11 08:33:5835 bool Try() EXCLUSIVE_TRYLOCK_FUNCTION(true) { return lock_.Try(); }
[email protected]32f3c232014-02-24 02:09:2936
37 // Null implementation if not debug.
Benoît Lizéd65e44bab2019-11-29 11:10:1738 void AssertAcquired() const ASSERT_EXCLUSIVE_LOCK() {}
[email protected]32f3c232014-02-24 02:09:2939#else
[email protected]bc581a682011-01-01 23:16:2040 Lock();
[email protected]34143d02013-04-09 01:40:2041 ~Lock();
[email protected]bc581a682011-01-01 23:16:2042
robliao7a8a904b2016-04-11 19:39:4243 // NOTE: We do not permit recursive locks and will commonly fire a DCHECK() if
44 // a thread attempts to acquire the lock a second time (while already holding
45 // it).
Benoît Lizéa38dbf5d2020-03-11 08:33:5846 void Acquire() EXCLUSIVE_LOCK_FUNCTION() {
[email protected]32f3c232014-02-24 02:09:2947 lock_.Lock();
48 CheckUnheldAndMark();
49 }
Benoît Lizéa38dbf5d2020-03-11 08:33:5850 void Release() UNLOCK_FUNCTION() {
[email protected]32f3c232014-02-24 02:09:2951 CheckHeldAndUnmark();
52 lock_.Unlock();
53 }
[email protected]bc581a682011-01-01 23:16:2054
Benoît Lizéa38dbf5d2020-03-11 08:33:5855 bool Try() EXCLUSIVE_TRYLOCK_FUNCTION(true) {
[email protected]32f3c232014-02-24 02:09:2956 bool rv = lock_.Try();
57 if (rv) {
58 CheckUnheldAndMark();
59 }
60 return rv;
61 }
[email protected]bc581a682011-01-01 23:16:2062
Benoît Lizéd65e44bab2019-11-29 11:10:1763 void AssertAcquired() const ASSERT_EXCLUSIVE_LOCK();
olli.raula7e1b45842015-09-11 13:06:1064#endif // DCHECK_IS_ON()
[email protected]bc581a682011-01-01 23:16:2065
fdorayd84dc062016-08-04 20:36:2666 // Whether Lock mitigates priority inversion when used from different thread
67 // priorities.
68 static bool HandlesMultipleThreadPriorities() {
Fabrice de Gans-Riberi306871de2018-05-16 19:38:3969#if defined(OS_WIN)
fdorayd84dc062016-08-04 20:36:2670 // Windows mitigates priority inversion by randomly boosting the priority of
71 // ready threads.
72 // https://msdn.microsoft.com/library/windows/desktop/ms684831.aspx
73 return true;
Fabrice de Gans-Riberi306871de2018-05-16 19:38:3974#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
75 // POSIX mitigates priority inversion by setting the priority of a thread
76 // holding a Lock to the maximum priority of any other thread waiting on it.
77 return internal::LockImpl::PriorityInheritanceAvailable();
fdorayd84dc062016-08-04 20:36:2678#else
79#error Unsupported platform
robliao2060718382016-08-01 20:59:4280#endif
fdorayd84dc062016-08-04 20:36:2681 }
robliao2060718382016-08-01 20:59:4282
robliaof11a6c02016-04-07 04:54:4283 // Both Windows and POSIX implementations of ConditionVariable need to be
84 // able to see our lock and tweak our debugging counters, as they release and
85 // acquire locks inside of their condition variable APIs.
[email protected]bc581a682011-01-01 23:16:2086 friend class ConditionVariable;
[email protected]bc581a682011-01-01 23:16:2087
[email protected]32f3c232014-02-24 02:09:2988 private:
olli.raula7e1b45842015-09-11 13:06:1089#if DCHECK_IS_ON()
[email protected]bc581a682011-01-01 23:16:2090 // Members and routines taking care of locks assertions.
91 // Note that this checks for recursive locks and allows them
92 // if the variable is set. This is allowed by the underlying implementation
93 // on windows but not on Posix, so we're doing unneeded checks on Posix.
94 // It's worth it to share the code.
95 void CheckHeldAndUnmark();
96 void CheckUnheldAndMark();
97
98 // All private data is implicitly protected by lock_.
99 // Be VERY careful to only access members under that lock.
[email protected]82952df2014-05-24 12:53:32100 base::PlatformThreadRef owning_thread_ref_;
olli.raula7e1b45842015-09-11 13:06:10101#endif // DCHECK_IS_ON()
[email protected]bc581a682011-01-01 23:16:20102
103 // Platform specific underlying lock implementation.
104 internal::LockImpl lock_;
105
106 DISALLOW_COPY_AND_ASSIGN(Lock);
107};
108
109// A helper class that acquires the given Lock while the AutoLock is in scope.
Etienne Pierre-doray8760a0952019-03-07 03:13:12110using AutoLock = internal::BasicAutoLock<Lock>;
[email protected]bc581a682011-01-01 23:16:20111
112// AutoUnlock is a helper that will Release() the |lock| argument in the
113// constructor, and re-Acquire() it in the destructor.
Etienne Pierre-doray8760a0952019-03-07 03:13:12114using AutoUnlock = internal::BasicAutoUnlock<Lock>;
[email protected]bc581a682011-01-01 23:16:20115
Gabriel Charetted773f122019-03-19 22:06:38116// Like AutoLock but is a no-op when the provided Lock* is null. Inspired from
117// absl::MutexLockMaybe. Use this instead of base::Optional<base::AutoLock> to
118// get around -Wthread-safety-analysis warnings for conditional locking.
119using AutoLockMaybe = internal::BasicAutoLockMaybe<Lock>;
120
121// Like AutoLock but permits Release() of its mutex before destruction.
122// Release() may be called at most once. Inspired from
123// absl::ReleasableMutexLock. Use this instead of base::Optional<base::AutoLock>
124// to get around -Wthread-safety-analysis warnings for AutoLocks that are
125// explicitly released early (prefer proper scoping to this).
126using ReleasableAutoLock = internal::BasicReleasableAutoLock<Lock>;
127
[email protected]bc581a682011-01-01 23:16:20128} // namespace base
129
130#endif // BASE_SYNCHRONIZATION_LOCK_H_