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