mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-28 00:06:09 +03:00
106 lines
3.6 KiB
C++
106 lines
3.6 KiB
C++
// 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_
|