1 // Copyright 2018 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/task/sequence_manager/associated_thread_id.h" 6 7 #include "base/check.h" 8 #include "base/dcheck_is_on.h" 9 10 namespace base { 11 namespace sequence_manager { 12 namespace internal { 13 14 AssociatedThreadId::AssociatedThreadId() = default; 15 AssociatedThreadId::~AssociatedThreadId() = default; 16 BindToCurrentThread()17void AssociatedThreadId::BindToCurrentThread() { 18 #if DCHECK_IS_ON() 19 const auto prev_thread_ref = 20 bound_thread_ref_.load(std::memory_order_relaxed); 21 DCHECK(prev_thread_ref.is_null() || 22 prev_thread_ref == PlatformThread::CurrentRef()); 23 #endif 24 sequence_token_ = base::internal::SequenceToken::GetForCurrentThread(); 25 bound_thread_ref_.store(PlatformThread::CurrentRef(), 26 std::memory_order_release); 27 28 // Rebind the thread and sequence checkers to the current thread/sequence. 29 DETACH_FROM_THREAD(thread_checker); 30 DCHECK_CALLED_ON_VALID_THREAD(thread_checker); 31 32 DETACH_FROM_SEQUENCE(sequence_checker); 33 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker); 34 } 35 IsBoundToCurrentThread() const36bool AssociatedThreadId::IsBoundToCurrentThread() const { 37 const PlatformThreadRef bound_thread_ref = 38 bound_thread_ref_.load(std::memory_order_relaxed); 39 const PlatformThreadRef in_sequence_thread_ref = 40 in_sequence_thread_ref_.load(std::memory_order_relaxed); 41 const PlatformThreadRef current_thread_ref = PlatformThread::CurrentRef(); 42 43 if (!in_sequence_thread_ref.is_null()) { 44 // The main thread cannot run when another thread is running "in sequence" 45 // with it. 46 CHECK_NE(current_thread_ref, bound_thread_ref); 47 } 48 49 return bound_thread_ref == current_thread_ref; 50 } 51 AssertInSequenceWithCurrentThread() const52void AssociatedThreadId::AssertInSequenceWithCurrentThread() const { 53 const PlatformThreadRef in_sequence_thread_ref = 54 in_sequence_thread_ref_.load(std::memory_order_relaxed); 55 56 if (!in_sequence_thread_ref.is_null()) { 57 CHECK_EQ(in_sequence_thread_ref, PlatformThread::CurrentRef()); 58 return; 59 } 60 61 #if DCHECK_IS_ON() 62 const PlatformThreadRef bound_thread_ref = 63 bound_thread_ref_.load(std::memory_order_relaxed); 64 if (!bound_thread_ref.is_null()) { 65 CHECK_EQ(bound_thread_ref, PlatformThread::CurrentRef()); 66 return; 67 } 68 69 DCHECK_CALLED_ON_VALID_THREAD(thread_checker); 70 #endif // DCHECK_IS_ON() 71 } 72 StartInSequenceWithCurrentThread()73void AssociatedThreadId::StartInSequenceWithCurrentThread() { 74 PlatformThreadRef expected = PlatformThreadRef(); 75 bool succeeded = in_sequence_thread_ref_.compare_exchange_strong( 76 expected, PlatformThread::CurrentRef(), std::memory_order_relaxed); 77 CHECK(succeeded); 78 } 79 StopInSequenceWithCurrentThread()80void AssociatedThreadId::StopInSequenceWithCurrentThread() { 81 PlatformThreadRef expected = PlatformThread::CurrentRef(); 82 bool succeeded = in_sequence_thread_ref_.compare_exchange_strong( 83 expected, PlatformThreadRef(), std::memory_order_relaxed); 84 CHECK(succeeded); 85 } 86 87 } // namespace internal 88 } // namespace sequence_manager 89 } // namespace base 90