1 // Copyright 2017 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/threading/sequence_local_storage_map.h" 6 7 #include <utility> 8 9 #include "base/lazy_instance.h" 10 #include "base/logging.h" 11 #include "base/threading/thread_local.h" 12 13 namespace base { 14 namespace internal { 15 16 namespace { 17 LazyInstance<ThreadLocalPointer<SequenceLocalStorageMap>>::Leaky 18 tls_current_sequence_local_storage = LAZY_INSTANCE_INITIALIZER; 19 } // namespace 20 21 SequenceLocalStorageMap::SequenceLocalStorageMap() = default; 22 23 SequenceLocalStorageMap::~SequenceLocalStorageMap() = default; 24 25 ScopedSetSequenceLocalStorageMapForCurrentThread:: ScopedSetSequenceLocalStorageMapForCurrentThread(SequenceLocalStorageMap * sequence_local_storage)26 ScopedSetSequenceLocalStorageMapForCurrentThread( 27 SequenceLocalStorageMap* sequence_local_storage) { 28 DCHECK(!tls_current_sequence_local_storage.Get().Get()); 29 tls_current_sequence_local_storage.Get().Set(sequence_local_storage); 30 } 31 32 ScopedSetSequenceLocalStorageMapForCurrentThread:: ~ScopedSetSequenceLocalStorageMapForCurrentThread()33 ~ScopedSetSequenceLocalStorageMapForCurrentThread() { 34 tls_current_sequence_local_storage.Get().Set(nullptr); 35 } 36 GetForCurrentThread()37SequenceLocalStorageMap& SequenceLocalStorageMap::GetForCurrentThread() { 38 SequenceLocalStorageMap* current_sequence_local_storage = 39 tls_current_sequence_local_storage.Get().Get(); 40 41 DCHECK(current_sequence_local_storage) 42 << "SequenceLocalStorageSlot cannot be used because no " 43 "SequenceLocalStorageMap was stored in TLS. Use " 44 "ScopedSetSequenceLocalStorageMapForCurrentThread to store a " 45 "SequenceLocalStorageMap object in TLS."; 46 47 return *current_sequence_local_storage; 48 } 49 Get(int slot_id)50void* SequenceLocalStorageMap::Get(int slot_id) { 51 const auto it = sls_map_.find(slot_id); 52 if (it == sls_map_.end()) 53 return nullptr; 54 return it->second.value(); 55 } 56 Set(int slot_id,SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair)57void SequenceLocalStorageMap::Set( 58 int slot_id, 59 SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair) { 60 auto it = sls_map_.find(slot_id); 61 62 if (it == sls_map_.end()) 63 sls_map_.emplace(slot_id, std::move(value_destructor_pair)); 64 else 65 it->second = std::move(value_destructor_pair); 66 67 // The maximum number of entries in the map is 256. This can be adjusted, but 68 // will require reviewing the choice of data structure for the map. 69 DCHECK_LE(sls_map_.size(), 256U); 70 } 71 ValueDestructorPair(void * value,DestructorFunc * destructor)72SequenceLocalStorageMap::ValueDestructorPair::ValueDestructorPair( 73 void* value, 74 DestructorFunc* destructor) 75 : value_(value), destructor_(destructor) {} 76 ~ValueDestructorPair()77SequenceLocalStorageMap::ValueDestructorPair::~ValueDestructorPair() { 78 if (value_) 79 destructor_(value_); 80 } 81 ValueDestructorPair(ValueDestructorPair && value_destructor_pair)82SequenceLocalStorageMap::ValueDestructorPair::ValueDestructorPair( 83 ValueDestructorPair&& value_destructor_pair) 84 : value_(value_destructor_pair.value_), 85 destructor_(value_destructor_pair.destructor_) { 86 value_destructor_pair.value_ = nullptr; 87 } 88 89 SequenceLocalStorageMap::ValueDestructorPair& operator =(ValueDestructorPair && value_destructor_pair)90SequenceLocalStorageMap::ValueDestructorPair::operator=( 91 ValueDestructorPair&& value_destructor_pair) { 92 // Destroy |value_| before overwriting it with a new value. 93 if (value_) 94 destructor_(value_); 95 96 value_ = value_destructor_pair.value_; 97 destructor_ = value_destructor_pair.destructor_; 98 99 value_destructor_pair.value_ = nullptr; 100 101 return *this; 102 } 103 104 } // namespace internal 105 } // namespace base 106