xref: /aosp_15_r20/external/libchrome/base/threading/scoped_blocking_call.h (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright 2017 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #ifndef BASE_THREADING_SCOPED_BLOCKING_CALL_H
6*635a8641SAndroid Build Coastguard Worker #define BASE_THREADING_SCOPED_BLOCKING_CALL_H
7*635a8641SAndroid Build Coastguard Worker 
8*635a8641SAndroid Build Coastguard Worker #include "base/base_export.h"
9*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
10*635a8641SAndroid Build Coastguard Worker 
11*635a8641SAndroid Build Coastguard Worker namespace base {
12*635a8641SAndroid Build Coastguard Worker 
13*635a8641SAndroid Build Coastguard Worker // BlockingType indicates the likelihood that a blocking call will actually
14*635a8641SAndroid Build Coastguard Worker // block.
15*635a8641SAndroid Build Coastguard Worker enum class BlockingType {
16*635a8641SAndroid Build Coastguard Worker   // The call might block (e.g. file I/O that might hit in memory cache).
17*635a8641SAndroid Build Coastguard Worker   MAY_BLOCK,
18*635a8641SAndroid Build Coastguard Worker   // The call will definitely block (e.g. cache already checked and now pinging
19*635a8641SAndroid Build Coastguard Worker   // server synchronously).
20*635a8641SAndroid Build Coastguard Worker   WILL_BLOCK
21*635a8641SAndroid Build Coastguard Worker };
22*635a8641SAndroid Build Coastguard Worker 
23*635a8641SAndroid Build Coastguard Worker namespace internal {
24*635a8641SAndroid Build Coastguard Worker class BlockingObserver;
25*635a8641SAndroid Build Coastguard Worker }
26*635a8641SAndroid Build Coastguard Worker 
27*635a8641SAndroid Build Coastguard Worker // This class must be instantiated in every scope where a blocking call is made.
28*635a8641SAndroid Build Coastguard Worker // CPU usage should be minimal within that scope. //base APIs that block
29*635a8641SAndroid Build Coastguard Worker // instantiate their own ScopedBlockingCall; it is not necessary to instantiate
30*635a8641SAndroid Build Coastguard Worker // another ScopedBlockingCall in the scope where these APIs are used.
31*635a8641SAndroid Build Coastguard Worker //
32*635a8641SAndroid Build Coastguard Worker // Good:
33*635a8641SAndroid Build Coastguard Worker //   Data data;
34*635a8641SAndroid Build Coastguard Worker //   {
35*635a8641SAndroid Build Coastguard Worker //     ScopedBlockingCall scoped_blocking_call(BlockingType::WILL_BLOCK);
36*635a8641SAndroid Build Coastguard Worker //     data = GetDataFromNetwork();
37*635a8641SAndroid Build Coastguard Worker //   }
38*635a8641SAndroid Build Coastguard Worker //   CPUIntensiveProcessing(data);
39*635a8641SAndroid Build Coastguard Worker //
40*635a8641SAndroid Build Coastguard Worker // Bad:
41*635a8641SAndroid Build Coastguard Worker //   ScopedBlockingCall scoped_blocking_call(BlockingType::WILL_BLOCK);
42*635a8641SAndroid Build Coastguard Worker //   Data data = GetDataFromNetwork();
43*635a8641SAndroid Build Coastguard Worker //   CPUIntensiveProcessing(data);  // CPU usage within a ScopedBlockingCall.
44*635a8641SAndroid Build Coastguard Worker //
45*635a8641SAndroid Build Coastguard Worker // Good:
46*635a8641SAndroid Build Coastguard Worker //   Data a;
47*635a8641SAndroid Build Coastguard Worker //   Data b;
48*635a8641SAndroid Build Coastguard Worker //   {
49*635a8641SAndroid Build Coastguard Worker //     ScopedBlockingCall scoped_blocking_call(BlockingType::MAY_BLOCK);
50*635a8641SAndroid Build Coastguard Worker //     a = GetDataFromMemoryCacheOrNetwork();
51*635a8641SAndroid Build Coastguard Worker //     b = GetDataFromMemoryCacheOrNetwork();
52*635a8641SAndroid Build Coastguard Worker //   }
53*635a8641SAndroid Build Coastguard Worker //   CPUIntensiveProcessing(a);
54*635a8641SAndroid Build Coastguard Worker //   CPUIntensiveProcessing(b);
55*635a8641SAndroid Build Coastguard Worker //
56*635a8641SAndroid Build Coastguard Worker // Bad:
57*635a8641SAndroid Build Coastguard Worker //   ScopedBlockingCall scoped_blocking_call(BlockingType::MAY_BLOCK);
58*635a8641SAndroid Build Coastguard Worker //   Data a = GetDataFromMemoryCacheOrNetwork();
59*635a8641SAndroid Build Coastguard Worker //   Data b = GetDataFromMemoryCacheOrNetwork();
60*635a8641SAndroid Build Coastguard Worker //   CPUIntensiveProcessing(a);  // CPU usage within a ScopedBlockingCall.
61*635a8641SAndroid Build Coastguard Worker //   CPUIntensiveProcessing(b);  // CPU usage within a ScopedBlockingCall.
62*635a8641SAndroid Build Coastguard Worker //
63*635a8641SAndroid Build Coastguard Worker // Good:
64*635a8641SAndroid Build Coastguard Worker //   base::WaitableEvent waitable_event(...);
65*635a8641SAndroid Build Coastguard Worker //   waitable_event.Wait();
66*635a8641SAndroid Build Coastguard Worker //
67*635a8641SAndroid Build Coastguard Worker // Bad:
68*635a8641SAndroid Build Coastguard Worker //  base::WaitableEvent waitable_event(...);
69*635a8641SAndroid Build Coastguard Worker //  ScopedBlockingCall scoped_blocking_call(BlockingType::WILL_BLOCK);
70*635a8641SAndroid Build Coastguard Worker //  waitable_event.Wait();  // Wait() instantiates its own ScopedBlockingCall.
71*635a8641SAndroid Build Coastguard Worker //
72*635a8641SAndroid Build Coastguard Worker // When a ScopedBlockingCall is instantiated from a TaskScheduler parallel or
73*635a8641SAndroid Build Coastguard Worker // sequenced task, the thread pool size is incremented to compensate for the
74*635a8641SAndroid Build Coastguard Worker // blocked thread (more or less aggressively depending on BlockingType).
75*635a8641SAndroid Build Coastguard Worker class BASE_EXPORT ScopedBlockingCall {
76*635a8641SAndroid Build Coastguard Worker  public:
77*635a8641SAndroid Build Coastguard Worker   ScopedBlockingCall(BlockingType blocking_type);
78*635a8641SAndroid Build Coastguard Worker   ~ScopedBlockingCall();
79*635a8641SAndroid Build Coastguard Worker 
80*635a8641SAndroid Build Coastguard Worker  private:
81*635a8641SAndroid Build Coastguard Worker   internal::BlockingObserver* const blocking_observer_;
82*635a8641SAndroid Build Coastguard Worker 
83*635a8641SAndroid Build Coastguard Worker   // Previous ScopedBlockingCall instantiated on this thread.
84*635a8641SAndroid Build Coastguard Worker   ScopedBlockingCall* const previous_scoped_blocking_call_;
85*635a8641SAndroid Build Coastguard Worker 
86*635a8641SAndroid Build Coastguard Worker   // Whether the BlockingType of the current thread was WILL_BLOCK after this
87*635a8641SAndroid Build Coastguard Worker   // ScopedBlockingCall was instantiated.
88*635a8641SAndroid Build Coastguard Worker   const bool is_will_block_;
89*635a8641SAndroid Build Coastguard Worker 
90*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(ScopedBlockingCall);
91*635a8641SAndroid Build Coastguard Worker };
92*635a8641SAndroid Build Coastguard Worker 
93*635a8641SAndroid Build Coastguard Worker namespace internal {
94*635a8641SAndroid Build Coastguard Worker 
95*635a8641SAndroid Build Coastguard Worker // Interface for an observer to be informed when a thread enters or exits
96*635a8641SAndroid Build Coastguard Worker // the scope of ScopedBlockingCall objects.
97*635a8641SAndroid Build Coastguard Worker class BASE_EXPORT BlockingObserver {
98*635a8641SAndroid Build Coastguard Worker  public:
99*635a8641SAndroid Build Coastguard Worker   virtual ~BlockingObserver() = default;
100*635a8641SAndroid Build Coastguard Worker 
101*635a8641SAndroid Build Coastguard Worker   // Invoked when a ScopedBlockingCall is instantiated on the observed thread
102*635a8641SAndroid Build Coastguard Worker   // where there wasn't an existing ScopedBlockingCall.
103*635a8641SAndroid Build Coastguard Worker   virtual void BlockingStarted(BlockingType blocking_type) = 0;
104*635a8641SAndroid Build Coastguard Worker 
105*635a8641SAndroid Build Coastguard Worker   // Invoked when a WILL_BLOCK ScopedBlockingCall is instantiated on the
106*635a8641SAndroid Build Coastguard Worker   // observed thread where there was a MAY_BLOCK ScopedBlockingCall but not a
107*635a8641SAndroid Build Coastguard Worker   // WILL_BLOCK ScopedBlockingCall.
108*635a8641SAndroid Build Coastguard Worker   virtual void BlockingTypeUpgraded() = 0;
109*635a8641SAndroid Build Coastguard Worker 
110*635a8641SAndroid Build Coastguard Worker   // Invoked when the last ScopedBlockingCall on the observed thread is
111*635a8641SAndroid Build Coastguard Worker   // destroyed.
112*635a8641SAndroid Build Coastguard Worker   virtual void BlockingEnded() = 0;
113*635a8641SAndroid Build Coastguard Worker };
114*635a8641SAndroid Build Coastguard Worker 
115*635a8641SAndroid Build Coastguard Worker // Registers |blocking_observer| on the current thread. It is invalid to call
116*635a8641SAndroid Build Coastguard Worker // this on a thread where there is an active ScopedBlockingCall.
117*635a8641SAndroid Build Coastguard Worker BASE_EXPORT void SetBlockingObserverForCurrentThread(
118*635a8641SAndroid Build Coastguard Worker     BlockingObserver* blocking_observer);
119*635a8641SAndroid Build Coastguard Worker 
120*635a8641SAndroid Build Coastguard Worker BASE_EXPORT void ClearBlockingObserverForTesting();
121*635a8641SAndroid Build Coastguard Worker 
122*635a8641SAndroid Build Coastguard Worker // Unregisters the |blocking_observer| on the current thread within its scope.
123*635a8641SAndroid Build Coastguard Worker // Used in TaskScheduler tests to prevent calls to //base sync primitives from
124*635a8641SAndroid Build Coastguard Worker // affecting the thread pool capacity.
125*635a8641SAndroid Build Coastguard Worker class BASE_EXPORT ScopedClearBlockingObserverForTesting {
126*635a8641SAndroid Build Coastguard Worker  public:
127*635a8641SAndroid Build Coastguard Worker   ScopedClearBlockingObserverForTesting();
128*635a8641SAndroid Build Coastguard Worker   ~ScopedClearBlockingObserverForTesting();
129*635a8641SAndroid Build Coastguard Worker 
130*635a8641SAndroid Build Coastguard Worker  private:
131*635a8641SAndroid Build Coastguard Worker   BlockingObserver* const blocking_observer_;
132*635a8641SAndroid Build Coastguard Worker 
133*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(ScopedClearBlockingObserverForTesting);
134*635a8641SAndroid Build Coastguard Worker };
135*635a8641SAndroid Build Coastguard Worker 
136*635a8641SAndroid Build Coastguard Worker }  // namespace internal
137*635a8641SAndroid Build Coastguard Worker 
138*635a8641SAndroid Build Coastguard Worker }  // namespace base
139*635a8641SAndroid Build Coastguard Worker 
140*635a8641SAndroid Build Coastguard Worker #endif  // BASE_THREADING_SCOPED_BLOCKING_CALL_H
141