• 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 #ifndef BASE_THREADING_SEQUENCE_LOCAL_STORAGE_SLOT_H_
6 #define BASE_THREADING_SEQUENCE_LOCAL_STORAGE_SLOT_H_
7 
8 #include <memory>
9 #include <utility>
10 
11 #include "base/base_export.h"
12 #include "base/template_util.h"
13 #include "base/threading/sequence_local_storage_map.h"
14 
15 namespace base {
16 
17 namespace internal {
18 BASE_EXPORT int GetNextSequenceLocalStorageSlotNumber();
19 }
20 
21 // SequenceLocalStorageSlot allows arbitrary values to be stored and retrieved
22 // from a sequence. Values are deleted when the sequence is deleted.
23 //
24 // Example usage:
25 //
26 // int& GetSequenceLocalStorage()
27 //     static base::NoDestructor<SequenceLocalStorageSlot<int>> sls_value;
28 //     return sls_value->GetOrCreateValue();
29 // }
30 //
31 // void Read() {
32 //   int value = GetSequenceLocalStorage();
33 //   ...
34 // }
35 //
36 // void Write() {
37 //   GetSequenceLocalStorage() = 42;
38 // }
39 //
40 // void PostTasks() {
41 //   // Since Read() runs on the same sequence as Write(), it
42 //   // will read the value "42". A Read() running on a different
43 //   // sequence would not see that value.
44 //   scoped_refptr<base::SequencedTaskRunner> task_runner = ...;
45 //   task_runner->PostTask(FROM_HERE, base::BindOnce(&Write));
46 //   task_runner->PostTask(FROM_HERE, base::BindOnce(&Read));
47 // }
48 //
49 // SequenceLocalStorageSlot must be used within the scope of a
50 // ScopedSetSequenceLocalStorageMapForCurrentThread object.
51 // Note: this is true on all ThreadPool workers and on threads bound to a
52 // MessageLoop.
53 template <typename T, typename Deleter = std::default_delete<T>>
54 class SequenceLocalStorageSlot {
55  public:
SequenceLocalStorageSlot()56   SequenceLocalStorageSlot()
57       : slot_id_(internal::GetNextSequenceLocalStorageSlotNumber()) {}
58 
59   SequenceLocalStorageSlot(const SequenceLocalStorageSlot&) = delete;
60   SequenceLocalStorageSlot& operator=(const SequenceLocalStorageSlot&) = delete;
61 
62   ~SequenceLocalStorageSlot() = default;
63 
64   operator bool() const { return GetValuePointer() != nullptr; }
65 
66   // Default-constructs the value for the current sequence if not
67   // already constructed. Then, returns the value.
GetOrCreateValue()68   T& GetOrCreateValue() {
69     T* ptr = GetValuePointer();
70     if (!ptr)
71       ptr = emplace();
72     return *ptr;
73   }
74 
75   // Returns a pointer to the value for the current sequence. May be
76   // nullptr if the value was not constructed on the current sequence.
GetValuePointer()77   T* GetValuePointer() {
78     void* ptr =
79         internal::SequenceLocalStorageMap::GetForCurrentThread().Get(slot_id_);
80     return static_cast<T*>(ptr);
81   }
GetValuePointer()82   const T* GetValuePointer() const {
83     return const_cast<SequenceLocalStorageSlot*>(this)->GetValuePointer();
84   }
85 
86   T* operator->() { return GetValuePointer(); }
87   const T* operator->() const { return GetValuePointer(); }
88 
89   T& operator*() { return *GetValuePointer(); }
90   const T& operator*() const { return *GetValuePointer(); }
91 
reset()92   void reset() { Adopt(nullptr); }
93 
94   // Constructs this slot's sequence-local value with |args...| and returns a
95   // pointer to the created object.
96   template <class... Args>
emplace(Args &&...args)97   T* emplace(Args&&... args) {
98     T* value_ptr = new T(std::forward<Args>(args)...);
99     Adopt(value_ptr);
100     return value_ptr;
101   }
102 
103  private:
104   // Takes ownership of |value_ptr|.
Adopt(T * value_ptr)105   void Adopt(T* value_ptr) {
106     // Since SequenceLocalStorageMap needs to store values of various types
107     // within the same map, the type of value_destructor_pair.value is void*
108     // (std::unique_ptr<void> is invalid). Memory is freed by calling
109     // |value_destructor_pair.destructor| in the destructor of
110     // ValueDestructorPair which is invoked when the value is overwritten by
111     // another call to SequenceLocalStorageMap::Set or when the
112     // SequenceLocalStorageMap is deleted.
113     internal::SequenceLocalStorageMap::ValueDestructorPair::DestructorFunc*
114         destructor = [](void* ptr) { Deleter()(static_cast<T*>(ptr)); };
115 
116     internal::SequenceLocalStorageMap::ValueDestructorPair
117         value_destructor_pair(value_ptr, destructor);
118 
119     internal::SequenceLocalStorageMap::GetForCurrentThread().Set(
120         slot_id_, std::move(value_destructor_pair));
121   }
122 
123   // |slot_id_| is used as a key in SequenceLocalStorageMap
124   const int slot_id_;
125 };
126 
127 }  // namespace base
128 #endif  // BASE_THREADING_SEQUENCE_LOCAL_STORAGE_SLOT_H_
129