xref: /aosp_15_r20/external/cronet/base/synchronization/lock.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2011 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_SYNCHRONIZATION_LOCK_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_SYNCHRONIZATION_LOCK_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h"
9*6777b538SAndroid Build Coastguard Worker #include "base/dcheck_is_on.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/lock_impl.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/thread_annotations.h"
12*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
15*6777b538SAndroid Build Coastguard Worker #include "base/threading/platform_thread_ref.h"
16*6777b538SAndroid Build Coastguard Worker #endif
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker namespace base {
19*6777b538SAndroid Build Coastguard Worker 
20*6777b538SAndroid Build Coastguard Worker // A convenient wrapper for an OS specific critical section.  The only real
21*6777b538SAndroid Build Coastguard Worker // intelligence in this class is in debug mode for the support for the
22*6777b538SAndroid Build Coastguard Worker // AssertAcquired() method.
23*6777b538SAndroid Build Coastguard Worker class LOCKABLE BASE_EXPORT Lock {
24*6777b538SAndroid Build Coastguard Worker  public:
25*6777b538SAndroid Build Coastguard Worker #if !DCHECK_IS_ON()
26*6777b538SAndroid Build Coastguard Worker   // Optimized wrapper implementation
Lock()27*6777b538SAndroid Build Coastguard Worker   Lock() : lock_() {}
28*6777b538SAndroid Build Coastguard Worker 
29*6777b538SAndroid Build Coastguard Worker   Lock(const Lock&) = delete;
30*6777b538SAndroid Build Coastguard Worker   Lock& operator=(const Lock&) = delete;
31*6777b538SAndroid Build Coastguard Worker 
~Lock()32*6777b538SAndroid Build Coastguard Worker   ~Lock() {}
33*6777b538SAndroid Build Coastguard Worker 
Acquire()34*6777b538SAndroid Build Coastguard Worker   void Acquire() EXCLUSIVE_LOCK_FUNCTION() { lock_.Lock(); }
Release()35*6777b538SAndroid Build Coastguard Worker   void Release() UNLOCK_FUNCTION() { lock_.Unlock(); }
36*6777b538SAndroid Build Coastguard Worker 
37*6777b538SAndroid Build Coastguard Worker   // If the lock is not held, take it and return true. If the lock is already
38*6777b538SAndroid Build Coastguard Worker   // held by another thread, immediately return false. This must not be called
39*6777b538SAndroid Build Coastguard Worker   // by a thread already holding the lock (what happens is undefined and an
40*6777b538SAndroid Build Coastguard Worker   // assertion may fail).
Try()41*6777b538SAndroid Build Coastguard Worker   bool Try() EXCLUSIVE_TRYLOCK_FUNCTION(true) { return lock_.Try(); }
42*6777b538SAndroid Build Coastguard Worker 
43*6777b538SAndroid Build Coastguard Worker   // Null implementation if not debug.
AssertAcquired()44*6777b538SAndroid Build Coastguard Worker   void AssertAcquired() const ASSERT_EXCLUSIVE_LOCK() {}
AssertNotHeld()45*6777b538SAndroid Build Coastguard Worker   void AssertNotHeld() const {}
46*6777b538SAndroid Build Coastguard Worker #else
47*6777b538SAndroid Build Coastguard Worker   Lock();
48*6777b538SAndroid Build Coastguard Worker   ~Lock();
49*6777b538SAndroid Build Coastguard Worker 
50*6777b538SAndroid Build Coastguard Worker   // NOTE: We do not permit recursive locks and will commonly fire a DCHECK() if
51*6777b538SAndroid Build Coastguard Worker   // a thread attempts to acquire the lock a second time (while already holding
52*6777b538SAndroid Build Coastguard Worker   // it).
53*6777b538SAndroid Build Coastguard Worker   void Acquire() EXCLUSIVE_LOCK_FUNCTION() {
54*6777b538SAndroid Build Coastguard Worker     lock_.Lock();
55*6777b538SAndroid Build Coastguard Worker     CheckUnheldAndMark();
56*6777b538SAndroid Build Coastguard Worker   }
57*6777b538SAndroid Build Coastguard Worker   void Release() UNLOCK_FUNCTION() {
58*6777b538SAndroid Build Coastguard Worker     CheckHeldAndUnmark();
59*6777b538SAndroid Build Coastguard Worker     lock_.Unlock();
60*6777b538SAndroid Build Coastguard Worker   }
61*6777b538SAndroid Build Coastguard Worker 
62*6777b538SAndroid Build Coastguard Worker   bool Try() EXCLUSIVE_TRYLOCK_FUNCTION(true) {
63*6777b538SAndroid Build Coastguard Worker     bool rv = lock_.Try();
64*6777b538SAndroid Build Coastguard Worker     if (rv) {
65*6777b538SAndroid Build Coastguard Worker       CheckUnheldAndMark();
66*6777b538SAndroid Build Coastguard Worker     }
67*6777b538SAndroid Build Coastguard Worker     return rv;
68*6777b538SAndroid Build Coastguard Worker   }
69*6777b538SAndroid Build Coastguard Worker 
70*6777b538SAndroid Build Coastguard Worker   void AssertAcquired() const ASSERT_EXCLUSIVE_LOCK();
71*6777b538SAndroid Build Coastguard Worker   void AssertNotHeld() const;
72*6777b538SAndroid Build Coastguard Worker #endif  // DCHECK_IS_ON()
73*6777b538SAndroid Build Coastguard Worker 
74*6777b538SAndroid Build Coastguard Worker   // Whether Lock mitigates priority inversion when used from different thread
75*6777b538SAndroid Build Coastguard Worker   // priorities.
HandlesMultipleThreadPriorities()76*6777b538SAndroid Build Coastguard Worker   static bool HandlesMultipleThreadPriorities() {
77*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
78*6777b538SAndroid Build Coastguard Worker     // Windows mitigates priority inversion by randomly boosting the priority of
79*6777b538SAndroid Build Coastguard Worker     // ready threads.
80*6777b538SAndroid Build Coastguard Worker     // https://msdn.microsoft.com/library/windows/desktop/ms684831.aspx
81*6777b538SAndroid Build Coastguard Worker     return true;
82*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
83*6777b538SAndroid Build Coastguard Worker     // POSIX mitigates priority inversion by setting the priority of a thread
84*6777b538SAndroid Build Coastguard Worker     // holding a Lock to the maximum priority of any other thread waiting on it.
85*6777b538SAndroid Build Coastguard Worker     return internal::LockImpl::PriorityInheritanceAvailable();
86*6777b538SAndroid Build Coastguard Worker #else
87*6777b538SAndroid Build Coastguard Worker #error Unsupported platform
88*6777b538SAndroid Build Coastguard Worker #endif
89*6777b538SAndroid Build Coastguard Worker   }
90*6777b538SAndroid Build Coastguard Worker 
91*6777b538SAndroid Build Coastguard Worker   // Both Windows and POSIX implementations of ConditionVariable need to be
92*6777b538SAndroid Build Coastguard Worker   // able to see our lock and tweak our debugging counters, as they release and
93*6777b538SAndroid Build Coastguard Worker   // acquire locks inside of their condition variable APIs.
94*6777b538SAndroid Build Coastguard Worker   friend class ConditionVariable;
95*6777b538SAndroid Build Coastguard Worker 
96*6777b538SAndroid Build Coastguard Worker  private:
97*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
98*6777b538SAndroid Build Coastguard Worker   // Members and routines taking care of locks assertions.
99*6777b538SAndroid Build Coastguard Worker   // Note that this checks for recursive locks and allows them
100*6777b538SAndroid Build Coastguard Worker   // if the variable is set.  This is allowed by the underlying implementation
101*6777b538SAndroid Build Coastguard Worker   // on windows but not on Posix, so we're doing unneeded checks on Posix.
102*6777b538SAndroid Build Coastguard Worker   // It's worth it to share the code.
103*6777b538SAndroid Build Coastguard Worker   void CheckHeldAndUnmark();
104*6777b538SAndroid Build Coastguard Worker   void CheckUnheldAndMark();
105*6777b538SAndroid Build Coastguard Worker 
106*6777b538SAndroid Build Coastguard Worker   // All private data is implicitly protected by lock_.
107*6777b538SAndroid Build Coastguard Worker   // Be VERY careful to only access members under that lock.
108*6777b538SAndroid Build Coastguard Worker   base::PlatformThreadRef owning_thread_ref_;
109*6777b538SAndroid Build Coastguard Worker #endif  // DCHECK_IS_ON()
110*6777b538SAndroid Build Coastguard Worker 
111*6777b538SAndroid Build Coastguard Worker   // Platform specific underlying lock implementation.
112*6777b538SAndroid Build Coastguard Worker   internal::LockImpl lock_;
113*6777b538SAndroid Build Coastguard Worker };
114*6777b538SAndroid Build Coastguard Worker 
115*6777b538SAndroid Build Coastguard Worker // A helper class that acquires the given Lock while the AutoLock is in scope.
116*6777b538SAndroid Build Coastguard Worker using AutoLock = internal::BasicAutoLock<Lock>;
117*6777b538SAndroid Build Coastguard Worker 
118*6777b538SAndroid Build Coastguard Worker // A helper class that tries to acquire the given Lock while the AutoTryLock is
119*6777b538SAndroid Build Coastguard Worker // in scope.
120*6777b538SAndroid Build Coastguard Worker using AutoTryLock = internal::BasicAutoTryLock<Lock>;
121*6777b538SAndroid Build Coastguard Worker 
122*6777b538SAndroid Build Coastguard Worker // AutoUnlock is a helper that will Release() the |lock| argument in the
123*6777b538SAndroid Build Coastguard Worker // constructor, and re-Acquire() it in the destructor.
124*6777b538SAndroid Build Coastguard Worker using AutoUnlock = internal::BasicAutoUnlock<Lock>;
125*6777b538SAndroid Build Coastguard Worker 
126*6777b538SAndroid Build Coastguard Worker // Like AutoLock but is a no-op when the provided Lock* is null. Inspired from
127*6777b538SAndroid Build Coastguard Worker // absl::MutexLockMaybe. Use this instead of std::optional<base::AutoLock> to
128*6777b538SAndroid Build Coastguard Worker // get around -Wthread-safety-analysis warnings for conditional locking.
129*6777b538SAndroid Build Coastguard Worker using AutoLockMaybe = internal::BasicAutoLockMaybe<Lock>;
130*6777b538SAndroid Build Coastguard Worker 
131*6777b538SAndroid Build Coastguard Worker // Like AutoLock but permits Release() of its mutex before destruction.
132*6777b538SAndroid Build Coastguard Worker // Release() may be called at most once. Inspired from
133*6777b538SAndroid Build Coastguard Worker // absl::ReleasableMutexLock. Use this instead of std::optional<base::AutoLock>
134*6777b538SAndroid Build Coastguard Worker // to get around -Wthread-safety-analysis warnings for AutoLocks that are
135*6777b538SAndroid Build Coastguard Worker // explicitly released early (prefer proper scoping to this).
136*6777b538SAndroid Build Coastguard Worker using ReleasableAutoLock = internal::BasicReleasableAutoLock<Lock>;
137*6777b538SAndroid Build Coastguard Worker 
138*6777b538SAndroid Build Coastguard Worker }  // namespace base
139*6777b538SAndroid Build Coastguard Worker 
140*6777b538SAndroid Build Coastguard Worker #endif  // BASE_SYNCHRONIZATION_LOCK_H_
141