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