xref: /aosp_15_r20/external/cronet/base/threading/scoped_blocking_call.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2017 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_THREADING_SCOPED_BLOCKING_CALL_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_THREADING_SCOPED_BLOCKING_CALL_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h"
9*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback_forward.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/location.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_piece.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/threading/scoped_blocking_call_internal.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/types/strong_alias.h"
14*6777b538SAndroid Build Coastguard Worker 
15*6777b538SAndroid Build Coastguard Worker namespace base {
16*6777b538SAndroid Build Coastguard Worker 
17*6777b538SAndroid Build Coastguard Worker // A "blocking call" refers to any call that causes the calling thread to wait
18*6777b538SAndroid Build Coastguard Worker // off-CPU. It includes but is not limited to calls that wait on synchronous
19*6777b538SAndroid Build Coastguard Worker // file I/O operations: read or write a file from disk, interact with a pipe or
20*6777b538SAndroid Build Coastguard Worker // a socket, rename or delete a file, enumerate files in a directory, etc.
21*6777b538SAndroid Build Coastguard Worker // Acquiring a low contention lock is not considered a blocking call.
22*6777b538SAndroid Build Coastguard Worker 
23*6777b538SAndroid Build Coastguard Worker // BlockingType indicates the likelihood that a blocking call will actually
24*6777b538SAndroid Build Coastguard Worker // block.
25*6777b538SAndroid Build Coastguard Worker enum class BlockingType {
26*6777b538SAndroid Build Coastguard Worker   // The call might block (e.g. file I/O that might hit in memory cache).
27*6777b538SAndroid Build Coastguard Worker   MAY_BLOCK,
28*6777b538SAndroid Build Coastguard Worker   // The call will definitely block (e.g. cache already checked and now pinging
29*6777b538SAndroid Build Coastguard Worker   // server synchronously).
30*6777b538SAndroid Build Coastguard Worker   WILL_BLOCK
31*6777b538SAndroid Build Coastguard Worker };
32*6777b538SAndroid Build Coastguard Worker 
33*6777b538SAndroid Build Coastguard Worker // This class must be instantiated in every scope where a blocking call is made
34*6777b538SAndroid Build Coastguard Worker // and serves as a precise annotation of the scope that may/will block for the
35*6777b538SAndroid Build Coastguard Worker // scheduler. When a ScopedBlockingCall is instantiated, it asserts that
36*6777b538SAndroid Build Coastguard Worker // blocking calls are allowed in its scope with a call to
37*6777b538SAndroid Build Coastguard Worker // base::AssertBlockingAllowed(). CPU usage should be minimal within that scope.
38*6777b538SAndroid Build Coastguard Worker // //base APIs that block instantiate their own ScopedBlockingCall; it is not
39*6777b538SAndroid Build Coastguard Worker // necessary to instantiate another ScopedBlockingCall in the scope where these
40*6777b538SAndroid Build Coastguard Worker // APIs are used. Nested ScopedBlockingCalls are supported (mostly a no-op
41*6777b538SAndroid Build Coastguard Worker // except for WILL_BLOCK nested within MAY_BLOCK which will result in immediate
42*6777b538SAndroid Build Coastguard Worker // WILL_BLOCK semantics).
43*6777b538SAndroid Build Coastguard Worker //
44*6777b538SAndroid Build Coastguard Worker // Good:
45*6777b538SAndroid Build Coastguard Worker //   Data data;
46*6777b538SAndroid Build Coastguard Worker //   {
47*6777b538SAndroid Build Coastguard Worker //     ScopedBlockingCall scoped_blocking_call(
48*6777b538SAndroid Build Coastguard Worker //         FROM_HERE, BlockingType::WILL_BLOCK);
49*6777b538SAndroid Build Coastguard Worker //     data = GetDataFromNetwork();
50*6777b538SAndroid Build Coastguard Worker //   }
51*6777b538SAndroid Build Coastguard Worker //   CPUIntensiveProcessing(data);
52*6777b538SAndroid Build Coastguard Worker //
53*6777b538SAndroid Build Coastguard Worker // Bad:
54*6777b538SAndroid Build Coastguard Worker //   ScopedBlockingCall scoped_blocking_call(FROM_HERE,
55*6777b538SAndroid Build Coastguard Worker //       BlockingType::WILL_BLOCK);
56*6777b538SAndroid Build Coastguard Worker //   Data data = GetDataFromNetwork();
57*6777b538SAndroid Build Coastguard Worker //   CPUIntensiveProcessing(data);  // CPU usage within a ScopedBlockingCall.
58*6777b538SAndroid Build Coastguard Worker //
59*6777b538SAndroid Build Coastguard Worker // Good:
60*6777b538SAndroid Build Coastguard Worker //   Data a;
61*6777b538SAndroid Build Coastguard Worker //   Data b;
62*6777b538SAndroid Build Coastguard Worker //   {
63*6777b538SAndroid Build Coastguard Worker //     ScopedBlockingCall scoped_blocking_call(
64*6777b538SAndroid Build Coastguard Worker //         FROM_HERE, BlockingType::MAY_BLOCK);
65*6777b538SAndroid Build Coastguard Worker //     a = GetDataFromMemoryCacheOrNetwork();
66*6777b538SAndroid Build Coastguard Worker //     b = GetDataFromMemoryCacheOrNetwork();
67*6777b538SAndroid Build Coastguard Worker //   }
68*6777b538SAndroid Build Coastguard Worker //   CPUIntensiveProcessing(a);
69*6777b538SAndroid Build Coastguard Worker //   CPUIntensiveProcessing(b);
70*6777b538SAndroid Build Coastguard Worker //
71*6777b538SAndroid Build Coastguard Worker // Bad:
72*6777b538SAndroid Build Coastguard Worker //   ScopedBlockingCall scoped_blocking_call(
73*6777b538SAndroid Build Coastguard Worker //       FROM_HERE, BlockingType::MAY_BLOCK);
74*6777b538SAndroid Build Coastguard Worker //   Data a = GetDataFromMemoryCacheOrNetwork();
75*6777b538SAndroid Build Coastguard Worker //   Data b = GetDataFromMemoryCacheOrNetwork();
76*6777b538SAndroid Build Coastguard Worker //   CPUIntensiveProcessing(a);  // CPU usage within a ScopedBlockingCall.
77*6777b538SAndroid Build Coastguard Worker //   CPUIntensiveProcessing(b);  // CPU usage within a ScopedBlockingCall.
78*6777b538SAndroid Build Coastguard Worker //
79*6777b538SAndroid Build Coastguard Worker // Good:
80*6777b538SAndroid Build Coastguard Worker //   base::WaitableEvent waitable_event(...);
81*6777b538SAndroid Build Coastguard Worker //   waitable_event.Wait();
82*6777b538SAndroid Build Coastguard Worker //
83*6777b538SAndroid Build Coastguard Worker // Bad:
84*6777b538SAndroid Build Coastguard Worker //  base::WaitableEvent waitable_event(...);
85*6777b538SAndroid Build Coastguard Worker //  ScopedBlockingCall scoped_blocking_call(
86*6777b538SAndroid Build Coastguard Worker //      FROM_HERE, BlockingType::WILL_BLOCK);
87*6777b538SAndroid Build Coastguard Worker //  waitable_event.Wait();  // Wait() instantiates its own ScopedBlockingCall.
88*6777b538SAndroid Build Coastguard Worker //
89*6777b538SAndroid Build Coastguard Worker // When a ScopedBlockingCall is instantiated from a ThreadPool parallel or
90*6777b538SAndroid Build Coastguard Worker // sequenced task, the thread pool size is incremented to compensate for the
91*6777b538SAndroid Build Coastguard Worker // blocked thread (more or less aggressively depending on BlockingType).
92*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT [[nodiscard]] ScopedBlockingCall
93*6777b538SAndroid Build Coastguard Worker     : public internal::UncheckedScopedBlockingCall {
94*6777b538SAndroid Build Coastguard Worker  public:
95*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCall(const Location& from_here, BlockingType blocking_type);
96*6777b538SAndroid Build Coastguard Worker   ~ScopedBlockingCall();
97*6777b538SAndroid Build Coastguard Worker };
98*6777b538SAndroid Build Coastguard Worker 
99*6777b538SAndroid Build Coastguard Worker // Usage reserved for //base callers.
100*6777b538SAndroid Build Coastguard Worker namespace internal {
101*6777b538SAndroid Build Coastguard Worker 
102*6777b538SAndroid Build Coastguard Worker // This class must be instantiated in every scope where a sync primitive is
103*6777b538SAndroid Build Coastguard Worker // used. When a ScopedBlockingCallWithBaseSyncPrimitives is instantiated, it
104*6777b538SAndroid Build Coastguard Worker // asserts that sync primitives are allowed in its scope with a call to
105*6777b538SAndroid Build Coastguard Worker // internal::AssertBaseSyncPrimitivesAllowed(). The same guidelines as for
106*6777b538SAndroid Build Coastguard Worker // ScopedBlockingCall should be followed.
107*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT [[nodiscard]] ScopedBlockingCallWithBaseSyncPrimitives
108*6777b538SAndroid Build Coastguard Worker     : public UncheckedScopedBlockingCall {
109*6777b538SAndroid Build Coastguard Worker  public:
110*6777b538SAndroid Build Coastguard Worker   ScopedBlockingCallWithBaseSyncPrimitives(const Location& from_here,
111*6777b538SAndroid Build Coastguard Worker                                            BlockingType blocking_type);
112*6777b538SAndroid Build Coastguard Worker   ~ScopedBlockingCallWithBaseSyncPrimitives();
113*6777b538SAndroid Build Coastguard Worker };
114*6777b538SAndroid Build Coastguard Worker 
115*6777b538SAndroid Build Coastguard Worker }  // namespace internal
116*6777b538SAndroid Build Coastguard Worker 
117*6777b538SAndroid Build Coastguard Worker using IOJankReportingCallback =
118*6777b538SAndroid Build Coastguard Worker     RepeatingCallback<void(int janky_intervals_per_minute,
119*6777b538SAndroid Build Coastguard Worker                            int total_janks_per_minute)>;
120*6777b538SAndroid Build Coastguard Worker using OnlyObservedThreadsForTest =
121*6777b538SAndroid Build Coastguard Worker     StrongAlias<class OnlyObservedThreadsTag, bool>;
122*6777b538SAndroid Build Coastguard Worker // Enables IO jank monitoring and reporting for this process. Should be called
123*6777b538SAndroid Build Coastguard Worker // at most once per process and only if
124*6777b538SAndroid Build Coastguard Worker // base::TimeTicks::IsConsistentAcrossProcesses() (the algorithm is unsafe
125*6777b538SAndroid Build Coastguard Worker // otherwise). |reporting_callback| will be invoked each time a monitoring
126*6777b538SAndroid Build Coastguard Worker // window completes, see internal::~IOJankMonitoringWindow() for details
127*6777b538SAndroid Build Coastguard Worker // (must be thread-safe). |only_observed_threads| can be set to true to have
128*6777b538SAndroid Build Coastguard Worker // the IOJank implementation ignore ScopedBlockingCalls on threads without a
129*6777b538SAndroid Build Coastguard Worker // BlockingObserver in tests that need to deterministically observe
130*6777b538SAndroid Build Coastguard Worker // ScopedBlockingCall side-effects.
131*6777b538SAndroid Build Coastguard Worker void BASE_EXPORT EnableIOJankMonitoringForProcess(
132*6777b538SAndroid Build Coastguard Worker     IOJankReportingCallback reporting_callback,
133*6777b538SAndroid Build Coastguard Worker     OnlyObservedThreadsForTest only_observed_threads =
134*6777b538SAndroid Build Coastguard Worker         OnlyObservedThreadsForTest(false));
135*6777b538SAndroid Build Coastguard Worker 
136*6777b538SAndroid Build Coastguard Worker }  // namespace base
137*6777b538SAndroid Build Coastguard Worker 
138*6777b538SAndroid Build Coastguard Worker #endif  // BASE_THREADING_SCOPED_BLOCKING_CALL_H_
139