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_(¤t_sequence_local_storage,
126 sequence_local_storage,
127 nullptr) {}
128
129 ScopedSetSequenceLocalStorageMapForCurrentThread::
130 ~ScopedSetSequenceLocalStorageMapForCurrentThread() = default;
131
132 } // namespace internal
133 } // namespace base
134