1 // Copyright 2016 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 #include "base/sequence_token.h" 6 7 #include "base/atomic_sequence_num.h" 8 #include "base/lazy_instance.h" 9 #include "base/logging.h" 10 #include "base/threading/thread_local.h" 11 12 namespace base { 13 14 namespace { 15 16 base::StaticAtomicSequenceNumber g_sequence_token_generator; 17 18 base::StaticAtomicSequenceNumber g_task_token_generator; 19 20 LazyInstance<ThreadLocalPointer<const SequenceToken>>::Leaky 21 tls_current_sequence_token = LAZY_INSTANCE_INITIALIZER; 22 23 LazyInstance<ThreadLocalPointer<const TaskToken>>::Leaky 24 tls_current_task_token = LAZY_INSTANCE_INITIALIZER; 25 26 } // namespace 27 28 bool SequenceToken::operator==(const SequenceToken& other) const { 29 return token_ == other.token_ && IsValid(); 30 } 31 32 bool SequenceToken::operator!=(const SequenceToken& other) const { 33 return !(*this == other); 34 } 35 36 bool SequenceToken::IsValid() const { 37 return token_ != kInvalidSequenceToken; 38 } 39 40 int SequenceToken::ToInternalValue() const { 41 return token_; 42 } 43 44 SequenceToken SequenceToken::Create() { 45 return SequenceToken(g_sequence_token_generator.GetNext()); 46 } 47 48 SequenceToken SequenceToken::GetForCurrentThread() { 49 const SequenceToken* current_sequence_token = 50 tls_current_sequence_token.Get().Get(); 51 return current_sequence_token ? *current_sequence_token : SequenceToken(); 52 } 53 54 bool TaskToken::operator==(const TaskToken& other) const { 55 return token_ == other.token_ && IsValid(); 56 } 57 58 bool TaskToken::operator!=(const TaskToken& other) const { 59 return !(*this == other); 60 } 61 62 bool TaskToken::IsValid() const { 63 return token_ != kInvalidTaskToken; 64 } 65 66 TaskToken TaskToken::Create() { 67 return TaskToken(g_task_token_generator.GetNext()); 68 } 69 70 TaskToken TaskToken::GetForCurrentThread() { 71 const TaskToken* current_task_token = tls_current_task_token.Get().Get(); 72 return current_task_token ? *current_task_token : TaskToken(); 73 } 74 75 ScopedSetSequenceTokenForCurrentThread::ScopedSetSequenceTokenForCurrentThread( 76 const SequenceToken& sequence_token) 77 : sequence_token_(sequence_token), task_token_(TaskToken::Create()) { 78 DCHECK(!tls_current_sequence_token.Get().Get()); 79 DCHECK(!tls_current_task_token.Get().Get()); 80 tls_current_sequence_token.Get().Set(&sequence_token_); 81 tls_current_task_token.Get().Set(&task_token_); 82 } 83 84 ScopedSetSequenceTokenForCurrentThread:: 85 ~ScopedSetSequenceTokenForCurrentThread() { 86 DCHECK_EQ(tls_current_sequence_token.Get().Get(), &sequence_token_); 87 DCHECK_EQ(tls_current_task_token.Get().Get(), &task_token_); 88 tls_current_sequence_token.Get().Set(nullptr); 89 tls_current_task_token.Get().Set(nullptr); 90 } 91 92 } // namespace base 93