| // Copyright 2017 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef BASE_THREADING_SEQUENCE_LOCAL_STORAGE_SLOT_H_ | 
 | #define BASE_THREADING_SEQUENCE_LOCAL_STORAGE_SLOT_H_ | 
 |  | 
 | #include <memory> | 
 | #include <utility> | 
 |  | 
 | #include "base/base_export.h" | 
 | #include "base/threading/sequence_local_storage_map.h" | 
 |  | 
 | namespace base { | 
 |  | 
 | namespace internal { | 
 | BASE_EXPORT int GetNextSequenceLocalStorageSlotNumber(); | 
 | } | 
 |  | 
 | // SequenceLocalStorageSlot allows arbitrary values to be stored and retrieved | 
 | // from a sequence. Values are deleted when the sequence is deleted. | 
 | // | 
 | // Example usage: | 
 | // | 
 | // namespace { | 
 | // base::LazyInstance<SequenceLocalStorageSlot<int>> sls_value; | 
 | // } | 
 | // | 
 | // void Read() { | 
 | //   int value = sls_value.Get().Get(); | 
 | //   ... | 
 | // } | 
 | // | 
 | // void Write() { | 
 | //   sls_value.Get().Set(42); | 
 | // } | 
 | // | 
 | // void PostTasks() { | 
 | //   // Since Read() runs on the same sequence as Write(), it | 
 | //   // will read the value "42". A Read() running on a different | 
 | //   // sequence would not see that value. | 
 | //   scoped_refptr<base::SequencedTaskRunner> task_runner = ...; | 
 | //   task_runner->PostTask(FROM_HERE, base::BindOnce(&Write)); | 
 | //   task_runner->PostTask(FROM_HERE, base::BindOnce(&Read)); | 
 | // } | 
 | // | 
 | // SequenceLocalStorageSlot must be used within the scope of a | 
 | // ScopedSetSequenceLocalStorageMapForCurrentThread object. | 
 | // Note: this is true on all TaskScheduler workers and on threads bound to a | 
 | // MessageLoop. | 
 | template <typename T, typename Deleter = std::default_delete<T>> | 
 | class SequenceLocalStorageSlot { | 
 |  public: | 
 |   SequenceLocalStorageSlot() | 
 |       : slot_id_(internal::GetNextSequenceLocalStorageSlotNumber()) {} | 
 |   ~SequenceLocalStorageSlot() = default; | 
 |  | 
 |   // Get the sequence-local value stored in this slot. Returns a | 
 |   // default-constructed value if no value was previously set. | 
 |   T& Get() { | 
 |     void* value = | 
 |         internal::SequenceLocalStorageMap::GetForCurrentThread().Get(slot_id_); | 
 |  | 
 |     // Sets and returns a default-constructed value if no value was previously | 
 |     // set. | 
 |     if (!value) { | 
 |       Set(T()); | 
 |       return Get(); | 
 |     } | 
 |     return *(static_cast<T*>(value)); | 
 |   } | 
 |  | 
 |   // Set this slot's sequence-local value to |value|. | 
 |   // Note that if T is expensive to copy, it may be more appropriate to instead | 
 |   // store a std::unique_ptr<T>. This is enforced by the | 
 |   // DISALLOW_COPY_AND_ASSIGN style rather than directly by this class however. | 
 |   void Set(T value) { | 
 |     // Allocates the |value| with new rather than std::make_unique. | 
 |     // Since SequenceLocalStorageMap needs to store values of various types | 
 |     // within the same map, the type of value_destructor_pair.value is void* | 
 |     // (std::unique_ptr<void> is invalid). Memory is freed by calling | 
 |     // |value_destructor_pair.destructor| in the destructor of | 
 |     // ValueDestructorPair which is invoked when the value is overwritten by | 
 |     // another call to SequenceLocalStorageMap::Set or when the | 
 |     // SequenceLocalStorageMap is deleted. | 
 |     T* value_ptr = new T(std::move(value)); | 
 |  | 
 |     internal::SequenceLocalStorageMap::ValueDestructorPair::DestructorFunc* | 
 |         destructor = [](void* ptr) { Deleter()(static_cast<T*>(ptr)); }; | 
 |  | 
 |     internal::SequenceLocalStorageMap::ValueDestructorPair | 
 |         value_destructor_pair(value_ptr, destructor); | 
 |  | 
 |     internal::SequenceLocalStorageMap::GetForCurrentThread().Set( | 
 |         slot_id_, std::move(value_destructor_pair)); | 
 |   } | 
 |  | 
 |  private: | 
 |   // |slot_id_| is used as a key in SequenceLocalStorageMap | 
 |   const int slot_id_; | 
 |   DISALLOW_COPY_AND_ASSIGN(SequenceLocalStorageSlot); | 
 | }; | 
 |  | 
 | }  // namespace base | 
 | #endif  // BASE_THREADING_SEQUENCE_LOCAL_STORAGE_SLOT_H_ |