| // 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 |