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