• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Chromium Authors
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 <ostream>
8 #include <utility>
9 
10 #include "base/check_op.h"
11 #include "base/sequence_token.h"
12 
13 namespace base {
14 namespace internal {
15 
16 namespace {
17 
18 constinit thread_local SequenceLocalStorageMap* current_sequence_local_storage =
19     nullptr;
20 
21 }  // namespace
22 
23 SequenceLocalStorageMap::SequenceLocalStorageMap() = default;
24 
25 SequenceLocalStorageMap::~SequenceLocalStorageMap() = default;
26 
27 // static
GetForCurrentThread()28 SequenceLocalStorageMap& SequenceLocalStorageMap::GetForCurrentThread() {
29   CHECK(!CurrentTaskIsRunningSynchronously());
30   DCHECK(IsSetForCurrentThread())
31       << "SequenceLocalStorageSlot cannot be used because no "
32          "SequenceLocalStorageMap was stored in TLS. Use "
33          "ScopedSetSequenceLocalStorageMapForCurrentThread to store a "
34          "SequenceLocalStorageMap object in TLS.";
35 
36   return *current_sequence_local_storage;
37 }
38 
39 // static
IsSetForCurrentThread()40 bool SequenceLocalStorageMap::IsSetForCurrentThread() {
41   return current_sequence_local_storage != nullptr;
42 }
43 
Has(int slot_id) const44 bool SequenceLocalStorageMap::Has(int slot_id) const {
45   return const_cast<SequenceLocalStorageMap*>(this)->Get(slot_id) != nullptr;
46 }
47 
Reset(int slot_id)48 void SequenceLocalStorageMap::Reset(int slot_id) {
49   sls_map_.erase(slot_id);
50 }
51 
Get(int slot_id)52 SequenceLocalStorageMap::Value* SequenceLocalStorageMap::Get(int slot_id) {
53   auto it = sls_map_.find(slot_id);
54   if (it != sls_map_.end()) {
55     return it->second.get();
56   }
57   return nullptr;
58 }
59 
Set(int slot_id,SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair)60 SequenceLocalStorageMap::Value* SequenceLocalStorageMap::Set(
61     int slot_id,
62     SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair) {
63   auto it = sls_map_.find(slot_id);
64 
65   if (it == sls_map_.end())
66     it = sls_map_.emplace(slot_id, std::move(value_destructor_pair)).first;
67   else
68     it->second = std::move(value_destructor_pair);
69 
70   // The maximum number of entries in the map is 256. This can be adjusted, but
71   // will require reviewing the choice of data structure for the map.
72   DCHECK_LE(sls_map_.size(), 256U);
73   return it->second.get();
74 }
75 
ValueDestructorPair()76 SequenceLocalStorageMap::ValueDestructorPair::ValueDestructorPair()
77     : destructor_(nullptr) {}
78 
ValueDestructorPair(ExternalValue value,DestructorFunc * destructor)79 SequenceLocalStorageMap::ValueDestructorPair::ValueDestructorPair(
80     ExternalValue value,
81     DestructorFunc* destructor)
82     : value_{.external_value = std::move(value)}, destructor_(destructor) {}
83 
ValueDestructorPair(InlineValue value,DestructorFunc * destructor)84 SequenceLocalStorageMap::ValueDestructorPair::ValueDestructorPair(
85     InlineValue value,
86     DestructorFunc* destructor)
87     : value_{.inline_value = std::move(value)}, destructor_(destructor) {}
88 
~ValueDestructorPair()89 SequenceLocalStorageMap::ValueDestructorPair::~ValueDestructorPair() {
90   if (destructor_) {
91     destructor_(&value_);
92   }
93 }
94 
ValueDestructorPair(ValueDestructorPair && value_destructor_pair)95 SequenceLocalStorageMap::ValueDestructorPair::ValueDestructorPair(
96     ValueDestructorPair&& value_destructor_pair)
97     : value_(value_destructor_pair.value_),
98       destructor_(value_destructor_pair.destructor_) {
99   value_destructor_pair.destructor_ = nullptr;
100 }
101 
102 SequenceLocalStorageMap::ValueDestructorPair&
operator =(ValueDestructorPair && value_destructor_pair)103 SequenceLocalStorageMap::ValueDestructorPair::operator=(
104     ValueDestructorPair&& value_destructor_pair) {
105   if (this == &value_destructor_pair) {
106     return *this;
107   }
108   // Destroy |value_| before overwriting it with a new value.
109   if (destructor_) {
110     destructor_(&value_);
111   }
112   value_ = value_destructor_pair.value_;
113   destructor_ = std::exchange(value_destructor_pair.destructor_, nullptr);
114 
115   return *this;
116 }
117 
operator bool() const118 SequenceLocalStorageMap::ValueDestructorPair::operator bool() const {
119   return destructor_ != nullptr;
120 }
121 
122 ScopedSetSequenceLocalStorageMapForCurrentThread::
ScopedSetSequenceLocalStorageMapForCurrentThread(SequenceLocalStorageMap * sequence_local_storage)123     ScopedSetSequenceLocalStorageMapForCurrentThread(
124         SequenceLocalStorageMap* sequence_local_storage)
125     : resetter_(&current_sequence_local_storage,
126                 sequence_local_storage,
127                 nullptr) {}
128 
129 ScopedSetSequenceLocalStorageMapForCurrentThread::
130     ~ScopedSetSequenceLocalStorageMapForCurrentThread() = default;
131 
132 }  // namespace internal
133 }  // namespace base
134