| // 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 <utility> | |
| #include "base/lazy_instance.h" | |
| #include "base/logging.h" | |
| #include "base/threading/thread_local.h" | |
| namespace base { | |
| namespace internal { | |
| namespace { | |
| LazyInstance<ThreadLocalPointer<SequenceLocalStorageMap>>::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); | |
| } | |
| 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; | |
| } | |
| 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 |