• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 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_THREADING_THREAD_CHECKER_H_
6 #define BASE_THREADING_THREAD_CHECKER_H_
7 
8 #include "base/compiler_specific.h"
9 #include "base/logging.h"
10 #include "base/threading/thread_checker_impl.h"
11 
12 // ThreadChecker is a helper class used to help verify that some methods of a
13 // class are called from the same thread (for thread-affinity).
14 //
15 // Use the macros below instead of the ThreadChecker directly so that the unused
16 // member doesn't result in an extra byte (four when padded) per instance in
17 // production.
18 //
19 // Usage of this class should be *rare* as most classes require thread-safety
20 // but not thread-affinity. Prefer base::SequenceChecker to verify thread-safe
21 // access.
22 //
23 // Thread-affinity checks should only be required in classes that use thread-
24 // local-storage or a third-party API that does.
25 //
26 // Prefer to encode the minimum requirements of each class instead of the
27 // environment it happens to run in today. e.g. if a class requires thread-
28 // safety but not thread-affinity, use a SequenceChecker even if it happens to
29 // run on a SingleThreadTaskRunner today. That makes it easier to understand
30 // what would need to change to turn that SingleThreadTaskRunner into a
31 // SequencedTaskRunner for ease of scheduling as well as minimizes side-effects
32 // if that change is made.
33 //
34 // Usage:
35 //   class MyClass {
36 //    public:
37 //     MyClass() {
38 //       // It's sometimes useful to detach on construction for objects that are
39 //       // constructed in one place and forever after used from another
40 //       // thread.
41 //       DETACH_FROM_THREAD(my_thread_checker_);
42 //     }
43 //
44 //     ~MyClass() {
45 //       // ThreadChecker doesn't automatically check it's destroyed on origin
46 //       // thread for the same reason it's sometimes detached in the
47 //       // constructor. It's okay to destroy off thread if the owner otherwise
48 //       // knows usage on the associated thread is done. If you're not
49 //       // detaching in the constructor, you probably want to explicitly check
50 //       // in the destructor.
51 //       DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_);
52 //     }
53 //
54 //     void MyMethod() {
55 //       DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_);
56 //       ... (do stuff) ...
57 //     }
58 //
59 //    private:
60 //     THREAD_CHECKER(my_thread_checker_);
61 //   }
62 
63 #if DCHECK_IS_ON()
64 #define THREAD_CHECKER(name) base::ThreadChecker name
65 #define DCHECK_CALLED_ON_VALID_THREAD(name) DCHECK((name).CalledOnValidThread())
66 #define DETACH_FROM_THREAD(name) (name).DetachFromThread()
67 #else  // DCHECK_IS_ON()
68 #define THREAD_CHECKER(name)
69 #define DCHECK_CALLED_ON_VALID_THREAD(name) EAT_STREAM_PARAMETERS
70 #define DETACH_FROM_THREAD(name)
71 #endif  // DCHECK_IS_ON()
72 
73 namespace base {
74 
75 // Do nothing implementation, for use in release mode.
76 //
77 // Note: You should almost always use the ThreadChecker class (through the above
78 // macros) to get the right version for your build configuration.
79 class ThreadCheckerDoNothing {
80  public:
81   ThreadCheckerDoNothing() = default;
CalledOnValidThread()82   bool CalledOnValidThread() const WARN_UNUSED_RESULT { return true; }
DetachFromThread()83   void DetachFromThread() {}
84 
85  private:
86   DISALLOW_COPY_AND_ASSIGN(ThreadCheckerDoNothing);
87 };
88 
89 // Note that ThreadCheckerImpl::CalledOnValidThread() returns false when called
90 // from tasks posted to SingleThreadTaskRunners bound to different sequences,
91 // even if the tasks happen to run on the same thread (e.g. two independent
92 // SingleThreadTaskRunners on the TaskScheduler that happen to share a thread).
93 #if DCHECK_IS_ON()
94 class ThreadChecker : public ThreadCheckerImpl {
95 };
96 #else
97 class ThreadChecker : public ThreadCheckerDoNothing {
98 };
99 #endif  // DCHECK_IS_ON()
100 
101 }  // namespace base
102 
103 #endif  // BASE_THREADING_THREAD_CHECKER_H_
104