// Copyright 2017 The Chromium Authors // 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/sequence_token.h" #include "third_party/abseil-cpp/absl/base/attributes.h" namespace base { namespace internal { namespace { ABSL_CONST_INIT thread_local SequenceLocalStorageMap* current_sequence_local_storage = nullptr; } // namespace SequenceLocalStorageMap::SequenceLocalStorageMap() = default; SequenceLocalStorageMap::~SequenceLocalStorageMap() = default; // static SequenceLocalStorageMap& SequenceLocalStorageMap::GetForCurrentThread() { CHECK(!CurrentTaskIsRunningSynchronously()); DCHECK(IsSetForCurrentThread()) << "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 current_sequence_local_storage != nullptr; } bool SequenceLocalStorageMap::Has(int slot_id) const { return const_cast(this)->Get(slot_id) != nullptr; } void SequenceLocalStorageMap::Reset(int slot_id) { sls_map_.erase(slot_id); } SequenceLocalStorageMap::Value* SequenceLocalStorageMap::Get(int slot_id) { auto it = sls_map_.find(slot_id); if (it != sls_map_.end()) { return it->second.get(); } return nullptr; } SequenceLocalStorageMap::Value* SequenceLocalStorageMap::Set( int slot_id, SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair) { auto it = sls_map_.find(slot_id); if (it == sls_map_.end()) it = sls_map_.emplace(slot_id, std::move(value_destructor_pair)).first; 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); return it->second.get(); } SequenceLocalStorageMap::ValueDestructorPair::ValueDestructorPair() : destructor_(nullptr) {} SequenceLocalStorageMap::ValueDestructorPair::ValueDestructorPair( ExternalValue value, DestructorFunc* destructor) : value_{.external_value = std::move(value)}, destructor_(destructor) {} SequenceLocalStorageMap::ValueDestructorPair::ValueDestructorPair( InlineValue value, DestructorFunc* destructor) : value_{.inline_value = std::move(value)}, destructor_(destructor) {} SequenceLocalStorageMap::ValueDestructorPair::~ValueDestructorPair() { if (destructor_) { destructor_(&value_); } } SequenceLocalStorageMap::ValueDestructorPair::ValueDestructorPair( ValueDestructorPair&& value_destructor_pair) : value_(value_destructor_pair.value_), destructor_(value_destructor_pair.destructor_) { value_destructor_pair.destructor_ = nullptr; } SequenceLocalStorageMap::ValueDestructorPair& SequenceLocalStorageMap::ValueDestructorPair::operator=( ValueDestructorPair&& value_destructor_pair) { if (this == &value_destructor_pair) { return *this; } // Destroy |value_| before overwriting it with a new value. if (destructor_) { destructor_(&value_); } value_ = value_destructor_pair.value_; destructor_ = std::exchange(value_destructor_pair.destructor_, nullptr); return *this; } SequenceLocalStorageMap::ValueDestructorPair::operator bool() const { return destructor_ != nullptr; } ScopedSetSequenceLocalStorageMapForCurrentThread:: ScopedSetSequenceLocalStorageMapForCurrentThread( SequenceLocalStorageMap* sequence_local_storage) : resetter_(¤t_sequence_local_storage, sequence_local_storage, nullptr) {} ScopedSetSequenceLocalStorageMapForCurrentThread:: ~ScopedSetSequenceLocalStorageMapForCurrentThread() = default; } // namespace internal } // namespace base