// Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/threading/sequence_local_storage_map.h" #include #include #include "base/check_op.h" #include "base/lazy_instance.h" #include "base/threading/thread_local.h" namespace base { namespace internal { namespace { LazyInstance>::Leaky tls_current_sequence_local_storage = LAZY_INSTANCE_INITIALIZER; } // namespace SequenceLocalStorageMap::SequenceLocalStorageMap() = default; SequenceLocalStorageMap::~SequenceLocalStorageMap() = default; ScopedSetSequenceLocalStorageMapForCurrentThread:: ScopedSetSequenceLocalStorageMapForCurrentThread( SequenceLocalStorageMap* sequence_local_storage) { DCHECK(!tls_current_sequence_local_storage.Get().Get()); tls_current_sequence_local_storage.Get().Set(sequence_local_storage); } ScopedSetSequenceLocalStorageMapForCurrentThread:: ~ScopedSetSequenceLocalStorageMapForCurrentThread() { tls_current_sequence_local_storage.Get().Set(nullptr); } // static SequenceLocalStorageMap& SequenceLocalStorageMap::GetForCurrentThread() { SequenceLocalStorageMap* current_sequence_local_storage = tls_current_sequence_local_storage.Get().Get(); DCHECK(current_sequence_local_storage) << "SequenceLocalStorageSlot cannot be used because no " "SequenceLocalStorageMap was stored in TLS. Use " "ScopedSetSequenceLocalStorageMapForCurrentThread to store a " "SequenceLocalStorageMap object in TLS."; return *current_sequence_local_storage; } // static bool SequenceLocalStorageMap::IsSetForCurrentThread() { return tls_current_sequence_local_storage.Get().Get() != nullptr; } void* SequenceLocalStorageMap::Get(int slot_id) { const auto it = sls_map_.find(slot_id); if (it == sls_map_.end()) return nullptr; return it->second.value(); } void SequenceLocalStorageMap::Set( int slot_id, SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair) { auto it = sls_map_.find(slot_id); if (it == sls_map_.end()) sls_map_.emplace(slot_id, std::move(value_destructor_pair)); else it->second = std::move(value_destructor_pair); // The maximum number of entries in the map is 256. This can be adjusted, but // will require reviewing the choice of data structure for the map. DCHECK_LE(sls_map_.size(), 256U); } SequenceLocalStorageMap::ValueDestructorPair::ValueDestructorPair( void* value, DestructorFunc* destructor) : value_(value), destructor_(destructor) {} SequenceLocalStorageMap::ValueDestructorPair::~ValueDestructorPair() { if (value_) destructor_(value_); } SequenceLocalStorageMap::ValueDestructorPair::ValueDestructorPair( ValueDestructorPair&& value_destructor_pair) : value_(value_destructor_pair.value_), destructor_(value_destructor_pair.destructor_) { value_destructor_pair.value_ = nullptr; } SequenceLocalStorageMap::ValueDestructorPair& SequenceLocalStorageMap::ValueDestructorPair::operator=( ValueDestructorPair&& value_destructor_pair) { // Destroy |value_| before overwriting it with a new value. if (value_) destructor_(value_); value_ = value_destructor_pair.value_; destructor_ = value_destructor_pair.destructor_; value_destructor_pair.value_ = nullptr; return *this; } } // namespace internal } // namespace base