Coverage Report

Created: 2026-04-09 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/brpc/src/butil/threading/thread_restrictions.h
Line
Count
Source
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 BUTIL_THREADING_THREAD_RESTRICTIONS_H_
6
#define BUTIL_THREADING_THREAD_RESTRICTIONS_H_
7
8
#include "butil/base_export.h"
9
#include "butil/basictypes.h"
10
11
// See comment at top of thread_checker.h
12
#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
13
#define ENABLE_THREAD_RESTRICTIONS 1
14
#else
15
#define ENABLE_THREAD_RESTRICTIONS 0
16
#endif
17
18
class AcceleratedPresenter;
19
class BrowserProcessImpl;
20
class HistogramSynchronizer;
21
class MetricsService;
22
class NativeBackendKWallet;
23
class ScopedAllowWaitForLegacyWebViewApi;
24
class TestingAutomationProvider;
25
26
namespace browser_sync {
27
class NonFrontendDataTypeController;
28
class UIModelWorker;
29
}
30
namespace cc {
31
class CompletionEvent;
32
}
33
namespace chromeos {
34
class AudioMixerAlsa;
35
class BlockingMethodCaller;
36
namespace system {
37
class StatisticsProviderImpl;
38
}
39
}
40
namespace chrome_browser_net {
41
class Predictor;
42
}
43
namespace content {
44
class BrowserGpuChannelHostFactory;
45
class BrowserShutdownProfileDumper;
46
class BrowserTestBase;
47
class GLHelper;
48
class GpuChannelHost;
49
class NestedMessagePumpAndroid;
50
class RenderWidgetHelper;
51
class ScopedAllowWaitForAndroidLayoutTests;
52
class TextInputClientMac;
53
}
54
namespace dbus {
55
class Bus;
56
}
57
namespace disk_cache {
58
class BackendImpl;
59
class InFlightIO;
60
}
61
namespace media {
62
class AudioOutputController;
63
}
64
namespace net {
65
class FileStreamPosix;
66
class FileStreamWin;
67
namespace internal {
68
class AddressTrackerLinux;
69
}
70
}
71
72
namespace remoting {
73
class AutoThread;
74
}
75
76
namespace butil {
77
78
namespace android {
79
class JavaHandlerThread;
80
}
81
82
class SequencedWorkerPool;
83
class SimpleThread;
84
class Thread;
85
class ThreadTestHelper;
86
87
// Certain behavior is disallowed on certain threads.  ThreadRestrictions helps
88
// enforce these rules.  Examples of such rules:
89
//
90
// * Do not do blocking IO (makes the thread janky)
91
// * Do not access Singleton/LazyInstance (may lead to shutdown crashes)
92
//
93
// Here's more about how the protection works:
94
//
95
// 1) If a thread should not be allowed to make IO calls, mark it:
96
//      butil::ThreadRestrictions::SetIOAllowed(false);
97
//    By default, threads *are* allowed to make IO calls.
98
//    In Chrome browser code, IO calls should be proxied to the File thread.
99
//
100
// 2) If a function makes a call that will go out to disk, check whether the
101
//    current thread is allowed:
102
//      butil::ThreadRestrictions::AssertIOAllowed();
103
//
104
//
105
// Style tip: where should you put AssertIOAllowed checks?  It's best
106
// if you put them as close to the disk access as possible, at the
107
// lowest level.  This rule is simple to follow and helps catch all
108
// callers.  For example, if your function GoDoSomeBlockingDiskCall()
109
// only calls other functions in Chrome and not fopen(), you should go
110
// add the AssertIOAllowed checks in the helper functions.
111
112
class BUTIL_EXPORT ThreadRestrictions {
113
 public:
114
  // Constructing a ScopedAllowIO temporarily allows IO for the current
115
  // thread.  Doing this is almost certainly always incorrect.
116
  class BUTIL_EXPORT ScopedAllowIO {
117
   public:
118
0
    ScopedAllowIO() { previous_value_ = SetIOAllowed(true); }
119
0
    ~ScopedAllowIO() { SetIOAllowed(previous_value_); }
120
   private:
121
    // Whether IO is allowed when the ScopedAllowIO was constructed.
122
    bool previous_value_;
123
124
    DISALLOW_COPY_AND_ASSIGN(ScopedAllowIO);
125
  };
126
127
  // Constructing a ScopedAllowSingleton temporarily allows accessing for the
128
  // current thread.  Doing this is almost always incorrect.
129
  class BUTIL_EXPORT ScopedAllowSingleton {
130
   public:
131
0
    ScopedAllowSingleton() { previous_value_ = SetSingletonAllowed(true); }
132
0
    ~ScopedAllowSingleton() { SetSingletonAllowed(previous_value_); }
133
   private:
134
    // Whether singleton use is allowed when the ScopedAllowSingleton was
135
    // constructed.
136
    bool previous_value_;
137
138
    DISALLOW_COPY_AND_ASSIGN(ScopedAllowSingleton);
139
  };
140
141
#if ENABLE_THREAD_RESTRICTIONS
142
  // Set whether the current thread to make IO calls.
143
  // Threads start out in the *allowed* state.
144
  // Returns the previous value.
145
  static bool SetIOAllowed(bool allowed);
146
147
  // Check whether the current thread is allowed to make IO calls,
148
  // and DCHECK if not.  See the block comment above the class for
149
  // a discussion of where to add these checks.
150
  static void AssertIOAllowed();
151
152
  // Set whether the current thread can use singletons.  Returns the previous
153
  // value.
154
  static bool SetSingletonAllowed(bool allowed);
155
156
  // Check whether the current thread is allowed to use singletons (Singleton /
157
  // LazyInstance).  DCHECKs if not.
158
  static void AssertSingletonAllowed();
159
160
  // Disable waiting on the current thread. Threads start out in the *allowed*
161
  // state. Returns the previous value.
162
  static void DisallowWaiting();
163
164
  // Check whether the current thread is allowed to wait, and DCHECK if not.
165
  static void AssertWaitAllowed();
166
#else
167
  // Inline the empty definitions of these functions so that they can be
168
  // compiled out.
169
  static bool SetIOAllowed(bool) { return true; }
170
  static void AssertIOAllowed() {}
171
  static bool SetSingletonAllowed(bool) { return true; }
172
  static void AssertSingletonAllowed() {}
173
  static void DisallowWaiting() {}
174
  static void AssertWaitAllowed() {}
175
#endif
176
177
 private:
178
  // DO NOT ADD ANY OTHER FRIEND STATEMENTS, talk to jam or brettw first.
179
  // BEGIN ALLOWED USAGE.
180
  friend class content::BrowserShutdownProfileDumper;
181
  friend class content::BrowserTestBase;
182
  friend class content::NestedMessagePumpAndroid;
183
  friend class content::RenderWidgetHelper;
184
  friend class content::ScopedAllowWaitForAndroidLayoutTests;
185
  friend class ::HistogramSynchronizer;
186
  friend class ::ScopedAllowWaitForLegacyWebViewApi;
187
  friend class ::TestingAutomationProvider;
188
  friend class cc::CompletionEvent;
189
  friend class remoting::AutoThread;
190
  friend class MessagePumpDefault;
191
  friend class SequencedWorkerPool;
192
  friend class SimpleThread;
193
  friend class Thread;
194
  friend class ThreadTestHelper;
195
  friend class PlatformThread;
196
  friend class android::JavaHandlerThread;
197
198
  // END ALLOWED USAGE.
199
  // BEGIN USAGE THAT NEEDS TO BE FIXED.
200
  friend class ::chromeos::AudioMixerAlsa;        // http://crbug.com/125206
201
  friend class ::chromeos::BlockingMethodCaller;  // http://crbug.com/125360
202
  friend class ::chromeos::system::StatisticsProviderImpl;  // http://crbug.com/125385
203
  friend class browser_sync::NonFrontendDataTypeController;  // http://crbug.com/19757
204
  friend class browser_sync::UIModelWorker;       // http://crbug.com/19757
205
  friend class chrome_browser_net::Predictor;     // http://crbug.com/78451
206
  friend class
207
      content::BrowserGpuChannelHostFactory;      // http://crbug.com/125248
208
  friend class content::GLHelper;                 // http://crbug.com/125415
209
  friend class content::GpuChannelHost;           // http://crbug.com/125264
210
  friend class content::TextInputClientMac;       // http://crbug.com/121917
211
  friend class dbus::Bus;                         // http://crbug.com/125222
212
  friend class disk_cache::BackendImpl;           // http://crbug.com/74623
213
  friend class disk_cache::InFlightIO;            // http://crbug.com/74623
214
  friend class media::AudioOutputController;      // http://crbug.com/120973
215
  friend class net::FileStreamPosix;              // http://crbug.com/115067
216
  friend class net::FileStreamWin;                // http://crbug.com/115067
217
  friend class net::internal::AddressTrackerLinux;  // http://crbug.com/125097
218
  friend class ::AcceleratedPresenter;            // http://crbug.com/125391
219
  friend class ::BrowserProcessImpl;              // http://crbug.com/125207
220
  friend class ::MetricsService;                  // http://crbug.com/124954
221
  friend class ::NativeBackendKWallet;            // http://crbug.com/125331
222
  // END USAGE THAT NEEDS TO BE FIXED.
223
224
#if ENABLE_THREAD_RESTRICTIONS
225
  static bool SetWaitAllowed(bool allowed);
226
#else
227
  static bool SetWaitAllowed(bool) { return true; }
228
#endif
229
  
230
  // FIXME(gejun): ScopedAllowWait can't be accessed by SequencedWorkerPool::Inner
231
  // in gcc 3.4 (SequencedWorkerPool is a friend class)
232
#if __GNUC__ == 3
233
public:
234
#endif
235
  // Constructing a ScopedAllowWait temporarily allows waiting on the current
236
  // thread.  Doing this is almost always incorrect, which is why we limit who
237
  // can use this through friend. If you find yourself needing to use this, find
238
  // another way. Talk to jam or brettw.
239
  class BUTIL_EXPORT ScopedAllowWait {
240
   public:
241
0
    ScopedAllowWait() { previous_value_ = SetWaitAllowed(true); }
242
0
    ~ScopedAllowWait() { SetWaitAllowed(previous_value_); }
243
   private:
244
    // Whether singleton use is allowed when the ScopedAllowWait was
245
    // constructed.
246
    bool previous_value_;
247
248
    DISALLOW_COPY_AND_ASSIGN(ScopedAllowWait);
249
  };
250
251
private:
252
  DISALLOW_IMPLICIT_CONSTRUCTORS(ThreadRestrictions);
253
};
254
255
}  // namespace butil
256
257
#endif  // BUTIL_THREADING_THREAD_RESTRICTIONS_H_