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