• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Chromium Authors. All rights reserved.
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/threading/sequence_local_storage_map.h"
13 
14 namespace base {
15 
16 namespace internal {
17 BASE_EXPORT int GetNextSequenceLocalStorageSlotNumber();
18 }
19 
20 // SequenceLocalStorageSlot allows arbitrary values to be stored and retrieved
21 // from a sequence. Values are deleted when the sequence is deleted.
22 //
23 // Example usage:
24 //
25 // namespace {
26 // base::LazyInstance<SequenceLocalStorageSlot<int>> sls_value;
27 // }
28 //
29 // void Read() {
30 //   int value = sls_value.Get().Get();
31 //   ...
32 // }
33 //
34 // void Write() {
35 //   sls_value.Get().Set(42);
36 // }
37 //
38 // void PostTasks() {
39 //   // Since Read() runs on the same sequence as Write(), it
40 //   // will read the value "42". A Read() running on a different
41 //   // sequence would not see that value.
42 //   scoped_refptr<base::SequencedTaskRunner> task_runner = ...;
43 //   task_runner->PostTask(FROM_HERE, base::BindOnce(&Write));
44 //   task_runner->PostTask(FROM_HERE, base::BindOnce(&Read));
45 // }
46 //
47 // SequenceLocalStorageSlot must be used within the scope of a
48 // ScopedSetSequenceLocalStorageMapForCurrentThread object.
49 // Note: this is true on all TaskScheduler workers and on threads bound to a
50 // MessageLoop.
51 template <typename T, typename Deleter = std::default_delete<T>>
52 class SequenceLocalStorageSlot {
53  public:
SequenceLocalStorageSlot()54   SequenceLocalStorageSlot()
55       : slot_id_(internal::GetNextSequenceLocalStorageSlotNumber()) {}
56   ~SequenceLocalStorageSlot() = default;
57 
58   // Get the sequence-local value stored in this slot. Returns a
59   // default-constructed value if no value was previously set.
Get()60   T& Get() {
61     void* value =
62         internal::SequenceLocalStorageMap::GetForCurrentThread().Get(slot_id_);
63 
64     // Sets and returns a default-constructed value if no value was previously
65     // set.
66     if (!value) {
67       Set(T());
68       return Get();
69     }
70     return *(static_cast<T*>(value));
71   }
72 
73   // Set this slot's sequence-local value to |value|.
74   // Note that if T is expensive to copy, it may be more appropriate to instead
75   // store a std::unique_ptr<T>. This is enforced by the
76   // DISALLOW_COPY_AND_ASSIGN style rather than directly by this class however.
Set(T value)77   void Set(T value) {
78     // Allocates the |value| with new rather than std::make_unique.
79     // Since SequenceLocalStorageMap needs to store values of various types
80     // within the same map, the type of value_destructor_pair.value is void*
81     // (std::unique_ptr<void> is invalid). Memory is freed by calling
82     // |value_destructor_pair.destructor| in the destructor of
83     // ValueDestructorPair which is invoked when the value is overwritten by
84     // another call to SequenceLocalStorageMap::Set or when the
85     // SequenceLocalStorageMap is deleted.
86     T* value_ptr = new T(std::move(value));
87 
88     internal::SequenceLocalStorageMap::ValueDestructorPair::DestructorFunc*
89         destructor = [](void* ptr) { Deleter()(static_cast<T*>(ptr)); };
90 
91     internal::SequenceLocalStorageMap::ValueDestructorPair
92         value_destructor_pair(value_ptr, destructor);
93 
94     internal::SequenceLocalStorageMap::GetForCurrentThread().Set(
95         slot_id_, std::move(value_destructor_pair));
96   }
97 
98  private:
99   // |slot_id_| is used as a key in SequenceLocalStorageMap
100   const int slot_id_;
101   DISALLOW_COPY_AND_ASSIGN(SequenceLocalStorageSlot);
102 };
103 
104 }  // namespace base
105 #endif  // BASE_THREADING_SEQUENCE_LOCAL_STORAGE_SLOT_H_
106