xref: /aosp_15_r20/external/cronet/base/task/common/checked_lock.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2016 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_TASK_COMMON_CHECKED_LOCK_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_TASK_COMMON_CHECKED_LOCK_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <optional>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/dcheck_is_on.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/memory/stack_allocated.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/condition_variable.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/lock.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/task/common/checked_lock_impl.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/thread_annotations.h"
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker namespace base {
19*6777b538SAndroid Build Coastguard Worker namespace internal {
20*6777b538SAndroid Build Coastguard Worker 
21*6777b538SAndroid Build Coastguard Worker // CheckedLock should be used anywhere a Lock would be used in the base/task
22*6777b538SAndroid Build Coastguard Worker // impl. When DCHECK_IS_ON(), lock checking occurs. Otherwise, CheckedLock is
23*6777b538SAndroid Build Coastguard Worker // equivalent to base::Lock.
24*6777b538SAndroid Build Coastguard Worker //
25*6777b538SAndroid Build Coastguard Worker // The shape of CheckedLock is as follows:
26*6777b538SAndroid Build Coastguard Worker // CheckedLock()
27*6777b538SAndroid Build Coastguard Worker //     Default constructor, no predecessor lock.
28*6777b538SAndroid Build Coastguard Worker //     DCHECKs
29*6777b538SAndroid Build Coastguard Worker //         On Acquisition if any CheckedLock is acquired on this thread.
30*6777b538SAndroid Build Coastguard Worker //             Okay if a universal predecessor is acquired.
31*6777b538SAndroid Build Coastguard Worker //
32*6777b538SAndroid Build Coastguard Worker // CheckedLock(const CheckedLock* predecessor)
33*6777b538SAndroid Build Coastguard Worker //     Constructor that specifies an allowed predecessor for that lock.
34*6777b538SAndroid Build Coastguard Worker //     DCHECKs
35*6777b538SAndroid Build Coastguard Worker //         On Construction if |predecessor| forms a predecessor lock cycle or
36*6777b538SAndroid Build Coastguard Worker //             is a universal successor.
37*6777b538SAndroid Build Coastguard Worker //         On Acquisition if the previous lock acquired on the thread is not
38*6777b538SAndroid Build Coastguard Worker //             either |predecessor| or a universal predecessor. Okay if there
39*6777b538SAndroid Build Coastguard Worker //             was no previous lock acquired.
40*6777b538SAndroid Build Coastguard Worker //
41*6777b538SAndroid Build Coastguard Worker // CheckedLock(UniversalPredecessor universal_predecessor)
42*6777b538SAndroid Build Coastguard Worker //     Constructor for a lock that will allow the acquisition of any lock after
43*6777b538SAndroid Build Coastguard Worker //     it, without needing to explicitly be named a predecessor (e.g. a root in
44*6777b538SAndroid Build Coastguard Worker //     a lock chain). Can only be acquired if no locks are currently held by
45*6777b538SAndroid Build Coastguard Worker //     this thread. DCHECKs
46*6777b538SAndroid Build Coastguard Worker //         On Acquisition if any CheckedLock is acquired on this thread.
47*6777b538SAndroid Build Coastguard Worker //
48*6777b538SAndroid Build Coastguard Worker // CheckedLock(UniversalSuccessor universal_successor)
49*6777b538SAndroid Build Coastguard Worker //     Constructor for a lock that will allow its acquisition after any other
50*6777b538SAndroid Build Coastguard Worker //     lock, without needing to explicitly name its predecessor (e.g. a leaf in
51*6777b538SAndroid Build Coastguard Worker //     a lock chain). Can not be acquired after another UniversalSuccessor lock.
52*6777b538SAndroid Build Coastguard Worker //     DCHECKs
53*6777b538SAndroid Build Coastguard Worker //         On Acquisition if there was a previously acquired lock on the thread
54*6777b538SAndroid Build Coastguard Worker //             and it was also a universal successor.
55*6777b538SAndroid Build Coastguard Worker //
56*6777b538SAndroid Build Coastguard Worker // void Acquire()
57*6777b538SAndroid Build Coastguard Worker //     Acquires the lock.
58*6777b538SAndroid Build Coastguard Worker //
59*6777b538SAndroid Build Coastguard Worker // void Release()
60*6777b538SAndroid Build Coastguard Worker //     Releases the lock.
61*6777b538SAndroid Build Coastguard Worker //
62*6777b538SAndroid Build Coastguard Worker // void AssertAcquired().
63*6777b538SAndroid Build Coastguard Worker //     DCHECKs if the lock is not acquired.
64*6777b538SAndroid Build Coastguard Worker //
65*6777b538SAndroid Build Coastguard Worker // ConditionVariable CreateConditionVariable()
66*6777b538SAndroid Build Coastguard Worker //     Creates a condition variable using this as a lock.
67*6777b538SAndroid Build Coastguard Worker 
68*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
69*6777b538SAndroid Build Coastguard Worker class LOCKABLE CheckedLock : public CheckedLockImpl {
70*6777b538SAndroid Build Coastguard Worker  public:
71*6777b538SAndroid Build Coastguard Worker   CheckedLock() = default;
CheckedLock(const CheckedLock * predecessor)72*6777b538SAndroid Build Coastguard Worker   explicit CheckedLock(const CheckedLock* predecessor)
73*6777b538SAndroid Build Coastguard Worker       : CheckedLockImpl(predecessor) {}
CheckedLock(UniversalPredecessor universal_predecessor)74*6777b538SAndroid Build Coastguard Worker   explicit CheckedLock(UniversalPredecessor universal_predecessor)
75*6777b538SAndroid Build Coastguard Worker       : CheckedLockImpl(universal_predecessor) {}
CheckedLock(UniversalSuccessor universal_successor)76*6777b538SAndroid Build Coastguard Worker   explicit CheckedLock(UniversalSuccessor universal_successor)
77*6777b538SAndroid Build Coastguard Worker       : CheckedLockImpl(universal_successor) {}
78*6777b538SAndroid Build Coastguard Worker };
79*6777b538SAndroid Build Coastguard Worker #else   // DCHECK_IS_ON()
80*6777b538SAndroid Build Coastguard Worker class LOCKABLE CheckedLock : public Lock {
81*6777b538SAndroid Build Coastguard Worker  public:
82*6777b538SAndroid Build Coastguard Worker   CheckedLock() = default;
83*6777b538SAndroid Build Coastguard Worker   explicit CheckedLock(const CheckedLock*) {}
84*6777b538SAndroid Build Coastguard Worker   explicit CheckedLock(UniversalPredecessor) {}
85*6777b538SAndroid Build Coastguard Worker   explicit CheckedLock(UniversalSuccessor) {}
86*6777b538SAndroid Build Coastguard Worker   static void AssertNoLockHeldOnCurrentThread() {}
87*6777b538SAndroid Build Coastguard Worker 
88*6777b538SAndroid Build Coastguard Worker   ConditionVariable CreateConditionVariable() {
89*6777b538SAndroid Build Coastguard Worker     return ConditionVariable(this);
90*6777b538SAndroid Build Coastguard Worker   }
91*6777b538SAndroid Build Coastguard Worker   void CreateConditionVariableAndEmplace(
92*6777b538SAndroid Build Coastguard Worker       std::optional<ConditionVariable>& opt) {
93*6777b538SAndroid Build Coastguard Worker     opt.emplace(this);
94*6777b538SAndroid Build Coastguard Worker   }
95*6777b538SAndroid Build Coastguard Worker };
96*6777b538SAndroid Build Coastguard Worker #endif  // DCHECK_IS_ON()
97*6777b538SAndroid Build Coastguard Worker 
98*6777b538SAndroid Build Coastguard Worker // Provides the same functionality as base::AutoLock for CheckedLock.
99*6777b538SAndroid Build Coastguard Worker using CheckedAutoLock = internal::BasicAutoLock<CheckedLock>;
100*6777b538SAndroid Build Coastguard Worker 
101*6777b538SAndroid Build Coastguard Worker // Provides the same functionality as base::AutoUnlock for CheckedLock.
102*6777b538SAndroid Build Coastguard Worker using CheckedAutoUnlock = internal::BasicAutoUnlock<CheckedLock>;
103*6777b538SAndroid Build Coastguard Worker 
104*6777b538SAndroid Build Coastguard Worker // Provides the same functionality as base::AutoLockMaybe for CheckedLock.
105*6777b538SAndroid Build Coastguard Worker using CheckedAutoLockMaybe = internal::BasicAutoLockMaybe<CheckedLock>;
106*6777b538SAndroid Build Coastguard Worker 
107*6777b538SAndroid Build Coastguard Worker // Informs the clang thread safety analysis that an aliased lock is acquired.
108*6777b538SAndroid Build Coastguard Worker // Because the clang thread safety analysis doesn't understand aliased locks
109*6777b538SAndroid Build Coastguard Worker // [1], this code wouldn't compile without AnnotateAcquiredLockAlias:
110*6777b538SAndroid Build Coastguard Worker //
111*6777b538SAndroid Build Coastguard Worker // class Example {
112*6777b538SAndroid Build Coastguard Worker //  public:
113*6777b538SAndroid Build Coastguard Worker //    CheckedLock lock_;
114*6777b538SAndroid Build Coastguard Worker //    int value = 0 GUARDED_BY(lock_);
115*6777b538SAndroid Build Coastguard Worker // };
116*6777b538SAndroid Build Coastguard Worker //
117*6777b538SAndroid Build Coastguard Worker // Example example;
118*6777b538SAndroid Build Coastguard Worker // CheckedLock* acquired = &example.lock_;
119*6777b538SAndroid Build Coastguard Worker // CheckedAutoLock auto_lock(*acquired);
120*6777b538SAndroid Build Coastguard Worker // AnnotateAcquiredLockAlias annotate(*acquired, example.lock_);
121*6777b538SAndroid Build Coastguard Worker // example.value = 42;  // Doesn't compile without |annotate|.
122*6777b538SAndroid Build Coastguard Worker //
123*6777b538SAndroid Build Coastguard Worker // [1] https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#no-alias-analysis
124*6777b538SAndroid Build Coastguard Worker class SCOPED_LOCKABLE AnnotateAcquiredLockAlias {
125*6777b538SAndroid Build Coastguard Worker   STACK_ALLOCATED();
126*6777b538SAndroid Build Coastguard Worker 
127*6777b538SAndroid Build Coastguard Worker  public:
128*6777b538SAndroid Build Coastguard Worker   // |acquired_lock| is an acquired lock. |lock_alias| is an alias of
129*6777b538SAndroid Build Coastguard Worker   // |acquired_lock|.
AnnotateAcquiredLockAlias(const CheckedLock & acquired_lock,const CheckedLock & lock_alias)130*6777b538SAndroid Build Coastguard Worker   AnnotateAcquiredLockAlias(const CheckedLock& acquired_lock,
131*6777b538SAndroid Build Coastguard Worker                             const CheckedLock& lock_alias)
132*6777b538SAndroid Build Coastguard Worker       EXCLUSIVE_LOCK_FUNCTION(lock_alias)
133*6777b538SAndroid Build Coastguard Worker       : acquired_lock_(acquired_lock) {
134*6777b538SAndroid Build Coastguard Worker     DCHECK_EQ(&acquired_lock, &lock_alias);
135*6777b538SAndroid Build Coastguard Worker     acquired_lock_.AssertAcquired();
136*6777b538SAndroid Build Coastguard Worker   }
137*6777b538SAndroid Build Coastguard Worker 
138*6777b538SAndroid Build Coastguard Worker   AnnotateAcquiredLockAlias(const AnnotateAcquiredLockAlias&) = delete;
139*6777b538SAndroid Build Coastguard Worker   AnnotateAcquiredLockAlias& operator=(const AnnotateAcquiredLockAlias&) =
140*6777b538SAndroid Build Coastguard Worker       delete;
141*6777b538SAndroid Build Coastguard Worker 
UNLOCK_FUNCTION()142*6777b538SAndroid Build Coastguard Worker   ~AnnotateAcquiredLockAlias() UNLOCK_FUNCTION() {
143*6777b538SAndroid Build Coastguard Worker     acquired_lock_.AssertAcquired();
144*6777b538SAndroid Build Coastguard Worker   }
145*6777b538SAndroid Build Coastguard Worker 
146*6777b538SAndroid Build Coastguard Worker  private:
147*6777b538SAndroid Build Coastguard Worker   const CheckedLock& acquired_lock_;
148*6777b538SAndroid Build Coastguard Worker };
149*6777b538SAndroid Build Coastguard Worker 
150*6777b538SAndroid Build Coastguard Worker }  // namespace internal
151*6777b538SAndroid Build Coastguard Worker }  // namespace base
152*6777b538SAndroid Build Coastguard Worker 
153*6777b538SAndroid Build Coastguard Worker #endif  // BASE_TASK_COMMON_CHECKED_LOCK_H_
154