• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // This file is a port of absl::thread_annotations.
16 //
17 // This header file contains macro definitions for thread safety annotations
18 // that allow developers to document the locking policies of multi-threaded
19 // code. The annotations can also help program analysis tools to identify
20 // potential thread safety issues.
21 //
22 // These annotations are implemented using compiler attributes. Using the macros
23 // defined here instead of raw attributes allow for portability and future
24 // compatibility.
25 //
26 // When referring to mutexes in the arguments of the attributes, you should
27 // use variable names or more complex expressions (e.g. my_object->mutex_)
28 // that evaluate to a concrete mutex object whenever possible. If the mutex
29 // you want to refer to is not in scope, you may use a member pointer
30 // (e.g. &MyClass::mutex_) to refer to a mutex in some (unknown) object.
31 
32 #ifndef ICING_ABSL_PORTS_THREAD_ANNOTATIONS_H_
33 #define ICING_ABSL_PORTS_THREAD_ANNOTATIONS_H_
34 
35 #if defined(__clang__)
36 #define ICING_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(x) __attribute__((x))
37 #else
38 #define ICING_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(x)  // no-op
39 #endif
40 
41 // ICING_GUARDED_BY()
42 //
43 // Documents if a shared field or global variable needs to be protected by a
44 // mutex. ICING_GUARDED_BY() allows the user to specify a particular mutex that
45 // should be held when accessing the annotated variable.
46 //
47 // Although this annotation (and ICING_PT_GUARDED_BY, below) cannot be applied
48 // to local variables, a local variable and its associated mutex can often be
49 // combined into a small class or struct, thereby allowing the annotation.
50 //
51 // Example:
52 //
53 //   class Foo {
54 //     Mutex mu_;
55 //     int p1_ ICING_GUARDED_BY(mu_);
56 //     ...
57 //   };
58 #define ICING_GUARDED_BY(x) \
59   ICING_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(guarded_by(x))
60 
61 // ICING_PT_GUARDED_BY()
62 //
63 // Documents if the memory location pointed to by a pointer should be guarded
64 // by a mutex when dereferencing the pointer.
65 //
66 // Example:
67 //   class Foo {
68 //     Mutex mu_;
69 //     int *p1_ ICING_PT_GUARDED_BY(mu_);
70 //     ...
71 //   };
72 //
73 // Note that a pointer variable to a shared memory location could itself be a
74 // shared variable.
75 //
76 // Example:
77 //
78 //   // `q_`, guarded by `mu1_`, points to a shared memory location that is
79 //   // guarded by `mu2_`:
80 //   int *q_ ICING_GUARDED_BY(mu1_) ICING_PT_GUARDED_BY(mu2_);
81 #define ICING_PT_GUARDED_BY(x) \
82   ICING_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(pt_guarded_by(x))
83 
84 // ICING_ACQUIRED_AFTER() / ICING_ACQUIRED_BEFORE()
85 //
86 // Documents the acquisition order between locks that can be held
87 // simultaneously by a thread. For any two locks that need to be annotated
88 // to establish an acquisition order, only one of them needs the annotation.
89 // (i.e. You don't have to annotate both locks with both ICING_ACQUIRED_AFTER
90 // and ICING_ACQUIRED_BEFORE.)
91 //
92 // As with ICING_GUARDED_BY, this is only applicable to mutexes that are shared
93 // fields or global variables.
94 //
95 // Example:
96 //
97 //   Mutex m1_;
98 //   Mutex m2_ ICING_ACQUIRED_AFTER(m1_);
99 #define ICING_ACQUIRED_AFTER(...) \
100   ICING_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(acquired_after(__VA_ARGS__))
101 
102 #define ICING_ACQUIRED_BEFORE(...) \
103   ICING_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(acquired_before(__VA_ARGS__))
104 
105 // ICING_EXCLUSIVE_LOCKS_REQUIRED() / ICING_SHARED_LOCKS_REQUIRED()
106 //
107 // Documents a function that expects a mutex to be held prior to entry.
108 // The mutex is expected to be held both on entry to, and exit from, the
109 // function.
110 //
111 // An exclusive lock allows read-write access to the guarded data member(s), and
112 // only one thread can acquire a lock exclusively at any one time. A shared lock
113 // allows read-only access, and any number of threads can acquire a shared lock
114 // concurrently.
115 //
116 // Generally, non-const methods should be annotated with
117 // ICING_EXCLUSIVE_LOCKS_REQUIRED, while const methods should be annotated with
118 // ICING_SHARED_LOCKS_REQUIRED.
119 //
120 // Example:
121 //
122 //   Mutex mu1, mu2;
123 //   int a ICING_GUARDED_BY(mu1);
124 //   int b ICING_GUARDED_BY(mu2);
125 //
126 //   void foo() ICING_EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... }
127 //   void bar() const ICING_SHARED_LOCKS_REQUIRED(mu1, mu2) { ... }
128 #define ICING_EXCLUSIVE_LOCKS_REQUIRED(...)   \
129   ICING_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \
130       exclusive_locks_required(__VA_ARGS__))
131 
132 #define ICING_SHARED_LOCKS_REQUIRED(...) \
133   ICING_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(shared_locks_required(__VA_ARGS__))
134 
135 // ICING_LOCKS_EXCLUDED()
136 //
137 // Documents the locks acquired in the body of the function. These locks
138 // cannot be held when calling this function.
139 #define ICING_LOCKS_EXCLUDED(...) \
140   ICING_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(locks_excluded(__VA_ARGS__))
141 
142 // ICING_LOCK_RETURNED()
143 //
144 // Documents a function that returns a mutex without acquiring it.  For example,
145 // a public getter method that returns a pointer to a private mutex should
146 // be annotated with ICING_LOCK_RETURNED.
147 #define ICING_LOCK_RETURNED(x) \
148   ICING_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(lock_returned(x))
149 
150 // ICING_LOCKABLE
151 //
152 // Documents if a class/type is a lockable type.
153 #define ICING_LOCKABLE \
154   ICING_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(lockable)
155 
156 // ICING_SCOPED_LOCKABLE
157 //
158 // Documents if a class does RAII locking.
159 // The constructor should use `ICING_LOCK_FUNCTION()` to specify the mutex that
160 // is acquired, and the destructor should use `ICING_UNLOCK_FUNCTION()` with no
161 // arguments; the analysis will assume that the destructor unlocks whatever the
162 // constructor locked.
163 #define ICING_SCOPED_LOCKABLE \
164   ICING_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(scoped_lockable)
165 
166 // ICING_EXCLUSIVE_LOCK_FUNCTION()
167 //
168 // Documents functions that acquire a lock in the body of a function, and do
169 // not release it.
170 #define ICING_EXCLUSIVE_LOCK_FUNCTION(...)    \
171   ICING_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \
172       exclusive_lock_function(__VA_ARGS__))
173 
174 // ICING_SHARED_LOCK_FUNCTION()
175 //
176 // Documents functions that acquire a shared (reader) lock in the body of a
177 // function, and do not release it.
178 #define ICING_SHARED_LOCK_FUNCTION(...) \
179   ICING_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(shared_lock_function(__VA_ARGS__))
180 
181 // ICING_UNLOCK_FUNCTION()
182 //
183 // Documents functions that expect a lock to be held on entry to the function,
184 // and release it in the body of the function.
185 #define ICING_UNLOCK_FUNCTION(...) \
186   ICING_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(unlock_function(__VA_ARGS__))
187 
188 // ICING_EXCLUSIVE_TRYLOCK_FUNCTION() / ICING_SHARED_TRYLOCK_FUNCTION()
189 //
190 // Documents functions that try to acquire a lock, and return success or failure
191 // (or a non-boolean value that can be interpreted as a boolean).
192 // The first argument should be `true` for functions that return `true` on
193 // success, or `false` for functions that return `false` on success. The second
194 // argument specifies the mutex that is locked on success. If unspecified, this
195 // mutex is assumed to be `this`.
196 #define ICING_EXCLUSIVE_TRYLOCK_FUNCTION(...) \
197   ICING_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \
198       exclusive_trylock_function(__VA_ARGS__))
199 
200 #define ICING_SHARED_TRYLOCK_FUNCTION(...)    \
201   ICING_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \
202       shared_trylock_function(__VA_ARGS__))
203 
204 // ICING_ASSERT_EXCLUSIVE_LOCK() / ICING_ASSERT_SHARED_LOCK()
205 //
206 // Documents functions that dynamically check to see if a lock is held, and fail
207 // if it is not held.
208 #define ICING_ASSERT_EXCLUSIVE_LOCK(...) \
209   ICING_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(assert_exclusive_lock(__VA_ARGS__))
210 
211 #define ICING_ASSERT_SHARED_LOCK(...) \
212   ICING_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(assert_shared_lock(__VA_ARGS__))
213 
214 #endif  // ICING_ABSL_PORTS_THREAD_ANNOTATIONS_H_
215