sequence_local_storage_slot.h 4.2 KB

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