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 #include "base/threading/scoped_blocking_call.h" 6*635a8641SAndroid Build Coastguard Worker 7*635a8641SAndroid Build Coastguard Worker #include "base/lazy_instance.h" 8*635a8641SAndroid Build Coastguard Worker #include "base/threading/thread_local.h" 9*635a8641SAndroid Build Coastguard Worker 10*635a8641SAndroid Build Coastguard Worker namespace base { 11*635a8641SAndroid Build Coastguard Worker 12*635a8641SAndroid Build Coastguard Worker namespace { 13*635a8641SAndroid Build Coastguard Worker 14*635a8641SAndroid Build Coastguard Worker LazyInstance<ThreadLocalPointer<internal::BlockingObserver>>::Leaky 15*635a8641SAndroid Build Coastguard Worker tls_blocking_observer = LAZY_INSTANCE_INITIALIZER; 16*635a8641SAndroid Build Coastguard Worker 17*635a8641SAndroid Build Coastguard Worker // Last ScopedBlockingCall instantiated on this thread. 18*635a8641SAndroid Build Coastguard Worker LazyInstance<ThreadLocalPointer<ScopedBlockingCall>>::Leaky 19*635a8641SAndroid Build Coastguard Worker tls_last_scoped_blocking_call = LAZY_INSTANCE_INITIALIZER; 20*635a8641SAndroid Build Coastguard Worker 21*635a8641SAndroid Build Coastguard Worker } // namespace 22*635a8641SAndroid Build Coastguard Worker ScopedBlockingCall(BlockingType blocking_type)23*635a8641SAndroid Build Coastguard WorkerScopedBlockingCall::ScopedBlockingCall(BlockingType blocking_type) 24*635a8641SAndroid Build Coastguard Worker : blocking_observer_(tls_blocking_observer.Get().Get()), 25*635a8641SAndroid Build Coastguard Worker previous_scoped_blocking_call_(tls_last_scoped_blocking_call.Get().Get()), 26*635a8641SAndroid Build Coastguard Worker is_will_block_(blocking_type == BlockingType::WILL_BLOCK || 27*635a8641SAndroid Build Coastguard Worker (previous_scoped_blocking_call_ && 28*635a8641SAndroid Build Coastguard Worker previous_scoped_blocking_call_->is_will_block_)) { 29*635a8641SAndroid Build Coastguard Worker tls_last_scoped_blocking_call.Get().Set(this); 30*635a8641SAndroid Build Coastguard Worker 31*635a8641SAndroid Build Coastguard Worker if (blocking_observer_) { 32*635a8641SAndroid Build Coastguard Worker if (!previous_scoped_blocking_call_) { 33*635a8641SAndroid Build Coastguard Worker blocking_observer_->BlockingStarted(blocking_type); 34*635a8641SAndroid Build Coastguard Worker } else if (blocking_type == BlockingType::WILL_BLOCK && 35*635a8641SAndroid Build Coastguard Worker !previous_scoped_blocking_call_->is_will_block_) { 36*635a8641SAndroid Build Coastguard Worker blocking_observer_->BlockingTypeUpgraded(); 37*635a8641SAndroid Build Coastguard Worker } 38*635a8641SAndroid Build Coastguard Worker } 39*635a8641SAndroid Build Coastguard Worker } 40*635a8641SAndroid Build Coastguard Worker ~ScopedBlockingCall()41*635a8641SAndroid Build Coastguard WorkerScopedBlockingCall::~ScopedBlockingCall() { 42*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(this, tls_last_scoped_blocking_call.Get().Get()); 43*635a8641SAndroid Build Coastguard Worker tls_last_scoped_blocking_call.Get().Set(previous_scoped_blocking_call_); 44*635a8641SAndroid Build Coastguard Worker if (blocking_observer_ && !previous_scoped_blocking_call_) 45*635a8641SAndroid Build Coastguard Worker blocking_observer_->BlockingEnded(); 46*635a8641SAndroid Build Coastguard Worker } 47*635a8641SAndroid Build Coastguard Worker 48*635a8641SAndroid Build Coastguard Worker namespace internal { 49*635a8641SAndroid Build Coastguard Worker SetBlockingObserverForCurrentThread(BlockingObserver * blocking_observer)50*635a8641SAndroid Build Coastguard Workervoid SetBlockingObserverForCurrentThread(BlockingObserver* blocking_observer) { 51*635a8641SAndroid Build Coastguard Worker DCHECK(!tls_blocking_observer.Get().Get()); 52*635a8641SAndroid Build Coastguard Worker tls_blocking_observer.Get().Set(blocking_observer); 53*635a8641SAndroid Build Coastguard Worker } 54*635a8641SAndroid Build Coastguard Worker ClearBlockingObserverForTesting()55*635a8641SAndroid Build Coastguard Workervoid ClearBlockingObserverForTesting() { 56*635a8641SAndroid Build Coastguard Worker tls_blocking_observer.Get().Set(nullptr); 57*635a8641SAndroid Build Coastguard Worker } 58*635a8641SAndroid Build Coastguard Worker ScopedClearBlockingObserverForTesting()59*635a8641SAndroid Build Coastguard WorkerScopedClearBlockingObserverForTesting::ScopedClearBlockingObserverForTesting() 60*635a8641SAndroid Build Coastguard Worker : blocking_observer_(tls_blocking_observer.Get().Get()) { 61*635a8641SAndroid Build Coastguard Worker tls_blocking_observer.Get().Set(nullptr); 62*635a8641SAndroid Build Coastguard Worker } 63*635a8641SAndroid Build Coastguard Worker 64*635a8641SAndroid Build Coastguard Worker ScopedClearBlockingObserverForTesting:: ~ScopedClearBlockingObserverForTesting()65*635a8641SAndroid Build Coastguard Worker ~ScopedClearBlockingObserverForTesting() { 66*635a8641SAndroid Build Coastguard Worker DCHECK(!tls_blocking_observer.Get().Get()); 67*635a8641SAndroid Build Coastguard Worker tls_blocking_observer.Get().Set(blocking_observer_); 68*635a8641SAndroid Build Coastguard Worker } 69*635a8641SAndroid Build Coastguard Worker 70*635a8641SAndroid Build Coastguard Worker } // namespace internal 71*635a8641SAndroid Build Coastguard Worker 72*635a8641SAndroid Build Coastguard Worker } // namespace base 73