summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Varga <pvarga@inf.u-szeged.hu>2019-07-03 15:39:37 +0200
committerPeter Varga <pvarga@inf.u-szeged.hu>2019-07-26 12:06:19 +0000
commit30a2bb61e6cee079273d649cfd8fb4ac9094a2ba (patch)
tree1e7f34f1ce32f04fd9935b9c9ab5ba8d62266f0e
parent7fcd21228ae9670e58954bc326890be10bc1ba4f (diff)
downloadqtwebengine-chromium-30a2bb61e6cee079273d649cfd8fb4ac9094a2ba.tar.gz
[Backport][Scheduler]: Revamp SequenceLocalStorage.
This CL fixes a few issues with SequenceLocalStorage: - Supports holding T with disabled copy/move constructor by adding emplace(). - Prevents auto default construction with GetValuePointer. - Query if SequenceLocalStorageSlot currently holds a value with operator bool(). - Update doc to use NoDestructor. This makes it possible to replace in many cases: SequenceLocalStorageSlot<unique_ptr<T>> with SequenceLocalStorageSlot<T> and auto ptr = sls.Get(); if (!ptr) { ptr = make_unique<T>(); sls.Set(ptr); } return *ptr; with return sls.GetOrCreateValue(); TBR=fdoray@chromium.org Change-Id: I3ebb4201fa6d0df296d4a4eaa9b90a1692f3a772 Commit-Queue: Etienne Pierre-Doray <etiennep@chromium.org> Reviewed-by: François Doray <fdoray@chromium.org> Cr-Commit-Position: refs/heads/master@{#664708} Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
-rw-r--r--chromium/base/threading/sequence_local_storage_slot.cc1
-rw-r--r--chromium/base/threading/sequence_local_storage_slot.h68
-rw-r--r--chromium/components/tracing/common/tracing_sampler_profiler.cc6
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/connector.cc40
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/message.cc12
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/sequence_local_sync_event_watcher.cc10
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc2
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.cc23
8 files changed, 78 insertions, 84 deletions
diff --git a/chromium/base/threading/sequence_local_storage_slot.cc b/chromium/base/threading/sequence_local_storage_slot.cc
index b7db40bb4fe..5ae1d9f47ae 100644
--- a/chromium/base/threading/sequence_local_storage_slot.cc
+++ b/chromium/base/threading/sequence_local_storage_slot.cc
@@ -23,4 +23,5 @@ int GetNextSequenceLocalStorageSlotNumber() {
}
} // namespace internal
+
} // namespace base
diff --git a/chromium/base/threading/sequence_local_storage_slot.h b/chromium/base/threading/sequence_local_storage_slot.h
index 1d6dd7c606b..b8a8496e2f3 100644
--- a/chromium/base/threading/sequence_local_storage_slot.h
+++ b/chromium/base/threading/sequence_local_storage_slot.h
@@ -9,6 +9,7 @@
#include <utility>
#include "base/base_export.h"
+#include "base/template_util.h"
#include "base/threading/sequence_local_storage_map.h"
namespace base {
@@ -22,17 +23,18 @@ BASE_EXPORT int GetNextSequenceLocalStorageSlotNumber();
//
// Example usage:
//
-// namespace {
-// base::LazyInstance<SequenceLocalStorageSlot<int>> sls_value;
+// int& GetSequenceLocalStorage()
+// static base::NoDestructor<SequenceLocalStorageSlot<int>> sls_value;
+// return sls_value->GetOrCreateValue();
// }
//
// void Read() {
-// int value = sls_value.Get().Get();
+// int value = GetSequenceLocalStorage();
// ...
// }
//
// void Write() {
-// sls_value.Get().Set(42);
+// GetSequenceLocalStorage() = 42;
// }
//
// void PostTasks() {
@@ -55,27 +57,48 @@ class 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 =
+ operator bool() const { return GetValuePointer() != nullptr; }
+
+ // Default-constructs the value for the current sequence if not
+ // already constructed. Then, returns the value.
+ T& GetOrCreateValue() {
+ T* ptr = GetValuePointer();
+ if (!ptr)
+ ptr = emplace();
+ return *ptr;
+ }
+
+ // Returns a pointer to the value for the current sequence. May be
+ // nullptr if the value was not constructed on the current sequence.
+ T* GetValuePointer() {
+ void* ptr =
internal::SequenceLocalStorageMap::GetForCurrentThread().Get(slot_id_);
+ return static_cast<T*>(ptr);
+ }
+ const T* GetValuePointer() const {
+ return const_cast<SequenceLocalStorageSlot*>(this)->GetValuePointer();
+ }
+
+ T* operator->() { return GetValuePointer(); }
+ const T* operator->() const { return GetValuePointer(); }
- // Sets and returns a default-constructed value if no value was previously
- // set.
- if (!value) {
- Set(T());
- return Get();
- }
- return *(static_cast<T*>(value));
+ T& operator*() { return *GetValuePointer(); }
+ const T& operator*() const { return *GetValuePointer(); }
+
+ void reset() { Adopt(nullptr); }
+
+ // Constructs this slot's sequence-local value with |args...| and returns a
+ // pointer to the created object.
+ template <class... Args>
+ T* emplace(Args&&... args) {
+ T* value_ptr = new T(std::forward<Args>(args)...);
+ Adopt(value_ptr);
+ return value_ptr;
}
- // 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.
+ private:
+ // Takes ownership of |value_ptr|.
+ void Adopt(T* value_ptr) {
// 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
@@ -83,8 +106,6 @@ class SequenceLocalStorageSlot {
// 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)); };
@@ -95,7 +116,6 @@ class SequenceLocalStorageSlot {
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);
diff --git a/chromium/components/tracing/common/tracing_sampler_profiler.cc b/chromium/components/tracing/common/tracing_sampler_profiler.cc
index 347cd783481..f295b55d16b 100644
--- a/chromium/components/tracing/common/tracing_sampler_profiler.cc
+++ b/chromium/components/tracing/common/tracing_sampler_profiler.cc
@@ -143,9 +143,9 @@ void TracingSamplerProfiler::CreateOnChildThread() {
using ProfilerSlot =
base::SequenceLocalStorageSlot<std::unique_ptr<TracingSamplerProfiler>>;
static base::NoDestructor<ProfilerSlot> slot;
- if (!slot.get()->Get()) {
- slot.get()->Set(base::WrapUnique(
- new TracingSamplerProfiler(base::PlatformThread::CurrentId())));
+ if (!*slot) {
+ slot->emplace(
+ new TracingSamplerProfiler(base::PlatformThread::CurrentId()));
}
}
diff --git a/chromium/mojo/public/cpp/bindings/lib/connector.cc b/chromium/mojo/public/cpp/bindings/lib/connector.cc
index 4f73c98ebdc..01c5c3b21b6 100644
--- a/chromium/mojo/public/cpp/bindings/lib/connector.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/connector.cc
@@ -7,12 +7,12 @@
#include <stdint.h>
#include "base/bind.h"
-#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop_current.h"
+#include "base/no_destructor.h"
#include "base/run_loop.h"
#include "base/synchronization/lock.h"
#include "base/threading/sequence_local_storage_slot.h"
@@ -32,13 +32,6 @@ namespace mojo {
namespace {
-// The NestingObserver for each thread. Note that this is always a
-// Connector::RunLoopNestingObserver; we use the base type here because that
-// subclass is private to Connector.
-base::LazyInstance<
- base::SequenceLocalStorageSlot<base::RunLoop::NestingObserver*>>::Leaky
- g_sls_nesting_observer = LAZY_INSTANCE_INITIALIZER;
-
// The default outgoing serialization mode for new Connectors.
Connector::OutgoingSerializationMode g_default_outgoing_serialization_mode =
Connector::OutgoingSerializationMode::kLazy;
@@ -80,15 +73,15 @@ class Connector::ActiveDispatchTracker {
// Watches the MessageLoop on the current thread. Notifies the current chain of
// ActiveDispatchTrackers when a nested run loop is started.
class Connector::RunLoopNestingObserver
- : public base::RunLoop::NestingObserver,
- public base::MessageLoopCurrent::DestructionObserver {
+ : public base::RunLoop::NestingObserver {
public:
RunLoopNestingObserver() {
base::RunLoop::AddNestingObserverOnCurrentThread(this);
- base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
}
- ~RunLoopNestingObserver() override {}
+ ~RunLoopNestingObserver() override {
+ base::RunLoop::RemoveNestingObserverOnCurrentThread(this);
+ }
// base::RunLoop::NestingObserver:
void OnBeginNestedRunLoop() override {
@@ -96,25 +89,16 @@ class Connector::RunLoopNestingObserver
top_tracker_->NotifyBeginNesting();
}
- // base::MessageLoopCurrent::DestructionObserver:
- void WillDestroyCurrentMessageLoop() override {
- base::RunLoop::RemoveNestingObserverOnCurrentThread(this);
- base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
- DCHECK_EQ(this, g_sls_nesting_observer.Get().Get());
- g_sls_nesting_observer.Get().Set(nullptr);
- delete this;
- }
-
static RunLoopNestingObserver* GetForThread() {
if (!base::MessageLoopCurrent::Get())
return nullptr;
- auto* observer = static_cast<RunLoopNestingObserver*>(
- g_sls_nesting_observer.Get().Get());
- if (!observer) {
- observer = new RunLoopNestingObserver;
- g_sls_nesting_observer.Get().Set(observer);
- }
- return observer;
+ // The NestingObserver for each thread. Note that this is always a
+ // Connector::RunLoopNestingObserver; we use the base type here because that
+ // subclass is private to Connector.
+ static base::NoDestructor<
+ base::SequenceLocalStorageSlot<RunLoopNestingObserver>>
+ sls_nesting_observer;
+ return &sls_nesting_observer->GetOrCreateValue();
}
private:
diff --git a/chromium/mojo/public/cpp/bindings/lib/message.cc b/chromium/mojo/public/cpp/bindings/lib/message.cc
index fa28aa4e51e..1019088895d 100644
--- a/chromium/mojo/public/cpp/bindings/lib/message.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/message.cc
@@ -516,17 +516,17 @@ bool PassThroughFilter::Accept(Message* message) {
SyncMessageResponseContext::SyncMessageResponseContext()
: outer_context_(current()) {
- g_sls_sync_response_context.Get().Set(this);
+ g_sls_sync_response_context.Get().emplace(this);
}
SyncMessageResponseContext::~SyncMessageResponseContext() {
DCHECK_EQ(current(), this);
- g_sls_sync_response_context.Get().Set(outer_context_);
+ g_sls_sync_response_context.Get().emplace(outer_context_);
}
// static
SyncMessageResponseContext* SyncMessageResponseContext::current() {
- return g_sls_sync_response_context.Get().Get();
+ return g_sls_sync_response_context.Get().GetOrCreateValue();
}
void SyncMessageResponseContext::ReportBadMessage(const std::string& error) {
@@ -558,17 +558,17 @@ MessageHeaderV2::MessageHeaderV2() = default;
MessageDispatchContext::MessageDispatchContext(Message* message)
: outer_context_(current()), message_(message) {
- g_sls_message_dispatch_context.Get().Set(this);
+ g_sls_message_dispatch_context.Get().emplace(this);
}
MessageDispatchContext::~MessageDispatchContext() {
DCHECK_EQ(current(), this);
- g_sls_message_dispatch_context.Get().Set(outer_context_);
+ g_sls_message_dispatch_context.Get().emplace(outer_context_);
}
// static
MessageDispatchContext* MessageDispatchContext::current() {
- return g_sls_message_dispatch_context.Get().Get();
+ return g_sls_message_dispatch_context.Get().GetOrCreateValue();
}
ReportBadMessageCallback MessageDispatchContext::GetBadMessageCallback() {
diff --git a/chromium/mojo/public/cpp/bindings/lib/sequence_local_sync_event_watcher.cc b/chromium/mojo/public/cpp/bindings/lib/sequence_local_sync_event_watcher.cc
index f4618ffbe80..6543802d2e1 100644
--- a/chromium/mojo/public/cpp/bindings/lib/sequence_local_sync_event_watcher.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/sequence_local_sync_event_watcher.cc
@@ -73,10 +73,7 @@ class SequenceLocalSyncEventWatcher::SequenceLocalState {
// Initializes a SequenceLocalState instance in sequence-local storage if
// not already initialized. Returns a WeakPtr to the stored state object.
static base::WeakPtr<SequenceLocalState> GetOrCreate() {
- auto& state_ptr = GetStorageSlot().Get();
- if (!state_ptr)
- state_ptr = std::make_unique<SequenceLocalState>();
- return state_ptr->weak_ptr_factory_.GetWeakPtr();
+ return GetStorageSlot().GetOrCreateValue().weak_ptr_factory_.GetWeakPtr();
}
// Registers a new watcher and returns an iterator into the WatcherStateMap to
@@ -108,7 +105,7 @@ class SequenceLocalSyncEventWatcher::SequenceLocalState {
if (registered_watchers_.empty()) {
// If no more watchers are registered, clear our sequence-local storage.
// Deletes |this|.
- GetStorageSlot().Get().reset();
+ GetStorageSlot().reset();
}
}
@@ -168,8 +165,7 @@ class SequenceLocalSyncEventWatcher::SequenceLocalState {
}
private:
- using StorageSlotType =
- base::SequenceLocalStorageSlot<std::unique_ptr<SequenceLocalState>>;
+ using StorageSlotType = base::SequenceLocalStorageSlot<SequenceLocalState>;
static StorageSlotType& GetStorageSlot() {
static base::NoDestructor<StorageSlotType> storage;
return *storage;
diff --git a/chromium/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc b/chromium/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc
index 2b359861d72..0188933a95a 100644
--- a/chromium/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc
@@ -47,7 +47,7 @@ GlobalSyncCallSettings& GetGlobalSettings() {
size_t& GetSequenceLocalScopedAllowCount() {
static base::NoDestructor<base::SequenceLocalStorageSlot<size_t>> count;
- return count->Get();
+ return count->GetOrCreateValue();
}
} // namespace
diff --git a/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.cc b/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.cc
index 2ac48334450..3278a76a676 100644
--- a/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.cc
@@ -6,36 +6,29 @@
#include <algorithm>
-#include "base/lazy_instance.h"
#include "base/logging.h"
+#include "base/no_destructor.h"
#include "base/stl_util.h"
#include "base/threading/sequence_local_storage_slot.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "mojo/public/c/system/core.h"
namespace mojo {
-namespace {
-
-base::LazyInstance<
- base::SequenceLocalStorageSlot<scoped_refptr<SyncHandleRegistry>>>::Leaky
- g_current_sync_handle_watcher = LAZY_INSTANCE_INITIALIZER;
-
-} // namespace
// static
scoped_refptr<SyncHandleRegistry> SyncHandleRegistry::current() {
+ static base::NoDestructor<
+ base::SequenceLocalStorageSlot<scoped_refptr<SyncHandleRegistry>>>
+ g_current_sync_handle_watcher;
+
// SyncMessageFilter can be used on threads without sequence-local storage
// being available. Those receive a unique, standalone SyncHandleRegistry.
if (!base::SequencedTaskRunnerHandle::IsSet())
return new SyncHandleRegistry();
- scoped_refptr<SyncHandleRegistry> result =
- g_current_sync_handle_watcher.Get().Get();
- if (!result) {
- result = new SyncHandleRegistry();
- g_current_sync_handle_watcher.Get().Set(result);
- }
- return result;
+ if (!*g_current_sync_handle_watcher)
+ g_current_sync_handle_watcher->emplace(new SyncHandleRegistry());
+ return *g_current_sync_handle_watcher->GetValuePointer();
}
bool SyncHandleRegistry::RegisterHandle(const Handle& handle,