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::AtomicSequenceNumber g_sequence_token_generator; 17 18 base::AtomicSequenceNumber 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 operator ==(const SequenceToken & other) const28bool SequenceToken::operator==(const SequenceToken& other) const { 29 return token_ == other.token_ && IsValid(); 30 } 31 operator !=(const SequenceToken & other) const32bool SequenceToken::operator!=(const SequenceToken& other) const { 33 return !(*this == other); 34 } 35 IsValid() const36bool SequenceToken::IsValid() const { 37 return token_ != kInvalidSequenceToken; 38 } 39 ToInternalValue() const40int SequenceToken::ToInternalValue() const { 41 return token_; 42 } 43 Create()44SequenceToken SequenceToken::Create() { 45 return SequenceToken(g_sequence_token_generator.GetNext()); 46 } 47 GetForCurrentThread()48SequenceToken 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 operator ==(const TaskToken & other) const54bool TaskToken::operator==(const TaskToken& other) const { 55 return token_ == other.token_ && IsValid(); 56 } 57 operator !=(const TaskToken & other) const58bool TaskToken::operator!=(const TaskToken& other) const { 59 return !(*this == other); 60 } 61 IsValid() const62bool TaskToken::IsValid() const { 63 return token_ != kInvalidTaskToken; 64 } 65 Create()66TaskToken TaskToken::Create() { 67 return TaskToken(g_task_token_generator.GetNext()); 68 } 69 GetForCurrentThread()70TaskToken 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 ScopedSetSequenceTokenForCurrentThread(const SequenceToken & sequence_token)75ScopedSetSequenceTokenForCurrentThread::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:: ~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