• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
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_THREADING_THREAD_CHECKER_H_
6 #define BASE_THREADING_THREAD_CHECKER_H_
7 
8 #include "base/base_export.h"
9 #include "base/dcheck_is_on.h"
10 #include "base/strings/string_piece.h"
11 #include "base/thread_annotations.h"
12 #include "base/threading/thread_checker_impl.h"
13 
14 // ThreadChecker is a helper class used to help verify that some methods of a
15 // class are called from the same thread (for thread-affinity).  It supports
16 // thread safety annotations (see base/thread_annotations.h).
17 //
18 // Use the macros below instead of the ThreadChecker directly so that the unused
19 // member doesn't result in an extra byte (four when padded) per instance in
20 // production.
21 //
22 // Usage of this class should be *rare* as most classes require thread-safety
23 // but not thread-affinity. Prefer base::SequenceChecker to verify thread-safe
24 // access.
25 //
26 // Thread-affinity checks should only be required in classes that use thread-
27 // local-storage or a third-party API that does.
28 //
29 // Prefer to encode the minimum requirements of each class instead of the
30 // environment it happens to run in today. e.g. if a class requires thread-
31 // safety but not thread-affinity, use a SequenceChecker even if it happens to
32 // run on a SingleThreadTaskRunner today. That makes it easier to understand
33 // what would need to change to turn that SingleThreadTaskRunner into a
34 // SequencedTaskRunner for ease of scheduling as well as minimizes side-effects
35 // if that change is made.
36 //
37 // Debugging:
38 //   If ThreadChecker::EnableStackLogging() is called beforehand, then when
39 //   ThreadChecker fails, in addition to crashing with a stack trace of where
40 //   the violation occurred, it will also dump a stack trace of where the
41 //   checker was bound to a thread.
42 //
43 // Usage:
44 //   class MyClass {
45 //    public:
46 //     MyClass() {
47 //       // It's sometimes useful to detach on construction for objects that are
48 //       // constructed in one place and forever after used from another
49 //       // thread.
50 //       DETACH_FROM_THREAD(thread_checker_);
51 //     }
52 //
53 //     ~MyClass() {
54 //       // ThreadChecker doesn't automatically check it's destroyed on origin
55 //       // thread for the same reason it's sometimes detached in the
56 //       // constructor. It's okay to destroy off thread if the owner otherwise
57 //       // knows usage on the associated thread is done. If you're not
58 //       // detaching in the constructor, you probably want to explicitly check
59 //       // in the destructor.
60 //       DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
61 //     }
62 //
63 //     void MyMethod() {
64 //       DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
65 //       ... (do stuff) ...
66 //     }
67 //
68 //     void MyOtherMethod()
69 //         VALID_CONTEXT_REQUIRED(thread_checker_) {
70 //       foo_ = 42;
71 //     }
72 //
73 //    private:
74 //     int foo_ GUARDED_BY_CONTEXT(thread_checker_);
75 //
76 //     THREAD_CHECKER(thread_checker_);
77 //   }
78 
79 #define THREAD_CHECKER_INTERNAL_CONCAT2(a, b) a##b
80 #define THREAD_CHECKER_INTERNAL_CONCAT(a, b) \
81   THREAD_CHECKER_INTERNAL_CONCAT2(a, b)
82 #define THREAD_CHECKER_INTERNAL_UID(prefix) \
83   THREAD_CHECKER_INTERNAL_CONCAT(prefix, __LINE__)
84 
85 #if DCHECK_IS_ON()
86 #define THREAD_CHECKER(name) base::ThreadChecker name
87 #define DCHECK_CALLED_ON_VALID_THREAD(name, ...)                 \
88   base::ScopedValidateThreadChecker THREAD_CHECKER_INTERNAL_UID( \
89       scoped_validate_thread_checker_)(name, ##__VA_ARGS__);
90 #define DETACH_FROM_THREAD(name) (name).DetachFromThread()
91 #else  // DCHECK_IS_ON()
92 #define THREAD_CHECKER(name) static_assert(true, "")
93 #define DCHECK_CALLED_ON_VALID_THREAD(name, ...) EAT_CHECK_STREAM_PARAMS()
94 #define DETACH_FROM_THREAD(name)
95 #endif  // DCHECK_IS_ON()
96 
97 namespace base {
98 
99 // Do nothing implementation, for use in release mode.
100 //
101 // Note: You should almost always use the ThreadChecker class (through the above
102 // macros) to get the right version for your build configuration.
103 // Note: This is only a check, not a "lock". It is marked "LOCKABLE" only in
104 // order to support thread_annotations.h.
105 class LOCKABLE ThreadCheckerDoNothing {
106  public:
EnableStackLogging()107   static void EnableStackLogging() {}
108 
109   ThreadCheckerDoNothing() = default;
110 
111   ThreadCheckerDoNothing(const ThreadCheckerDoNothing&) = delete;
112   ThreadCheckerDoNothing& operator=(const ThreadCheckerDoNothing&) = delete;
113 
114   // Moving between matching threads is allowed to help classes with
115   // ThreadCheckers that want a default move-construct/assign.
116   ThreadCheckerDoNothing(ThreadCheckerDoNothing&& other) = default;
117   ThreadCheckerDoNothing& operator=(ThreadCheckerDoNothing&& other) = default;
118 
119   [[nodiscard]] bool CalledOnValidThread(
120       std::unique_ptr<void*> = nullptr) const {
121     return true;
122   }
DetachFromThread()123   void DetachFromThread() {}
124 };
125 
126 // Note that ThreadCheckerImpl::CalledOnValidThread() returns false when called
127 // from tasks posted to SingleThreadTaskRunners bound to different sequences,
128 // even if the tasks happen to run on the same thread (e.g. two independent
129 // SingleThreadTaskRunners on the ThreadPool that happen to share a thread).
130 #if DCHECK_IS_ON()
131 class ThreadChecker : public ThreadCheckerImpl {
132 };
133 #else
134 class ThreadChecker : public ThreadCheckerDoNothing {
135 };
136 #endif  // DCHECK_IS_ON()
137 
138 #if DCHECK_IS_ON()
139 class BASE_EXPORT SCOPED_LOCKABLE ScopedValidateThreadChecker {
140  public:
141   explicit ScopedValidateThreadChecker(const ThreadChecker& checker)
142       EXCLUSIVE_LOCK_FUNCTION(checker);
143   ScopedValidateThreadChecker(const ThreadChecker& checker,
144                               const StringPiece& msg)
145       EXCLUSIVE_LOCK_FUNCTION(checker);
146 
147   ScopedValidateThreadChecker(const ScopedValidateThreadChecker&) = delete;
148   ScopedValidateThreadChecker& operator=(const ScopedValidateThreadChecker&) =
149       delete;
150 
151   ~ScopedValidateThreadChecker() UNLOCK_FUNCTION();
152 };
153 #endif
154 
155 }  // namespace base
156 
157 #endif  // BASE_THREADING_THREAD_CHECKER_H_
158