mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2025-03-25 09:33:56 +03:00
115 lines
3.3 KiB
C++
115 lines
3.3 KiB
C++
// Copyright 2022 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "base/allocator/dispatcher/dispatcher.h"
|
|
|
|
#include "base/allocator/dispatcher/internal/dispatch_data.h"
|
|
#include "base/check.h"
|
|
#include "base/dcheck_is_on.h"
|
|
#include "base/no_destructor.h"
|
|
#include "partition_alloc/partition_alloc_buildflags.h"
|
|
#include "partition_alloc/shim/allocator_shim.h"
|
|
|
|
#if DCHECK_IS_ON()
|
|
#include <atomic>
|
|
#endif
|
|
|
|
#if BUILDFLAG(USE_PARTITION_ALLOC)
|
|
#include "partition_alloc/partition_alloc_hooks.h"
|
|
#endif
|
|
|
|
namespace base::allocator::dispatcher {
|
|
|
|
// The private implementation of Dispatcher.
|
|
struct Dispatcher::Impl {
|
|
void Initialize(const internal::DispatchData& dispatch_data) {
|
|
#if DCHECK_IS_ON()
|
|
DCHECK(!is_initialized_check_flag_.test_and_set());
|
|
#endif
|
|
|
|
dispatch_data_ = dispatch_data;
|
|
ConnectToEmitters(dispatch_data_);
|
|
}
|
|
|
|
void Reset() {
|
|
#if DCHECK_IS_ON()
|
|
DCHECK([&]() {
|
|
auto const was_set = is_initialized_check_flag_.test_and_set();
|
|
is_initialized_check_flag_.clear();
|
|
return was_set;
|
|
}());
|
|
#endif
|
|
|
|
DisconnectFromEmitters(dispatch_data_);
|
|
dispatch_data_ = {};
|
|
}
|
|
|
|
private:
|
|
// Connect the hooks to the memory subsystem. In some cases, most notably when
|
|
// we have no observers at all, the hooks will be invalid and must NOT be
|
|
// connected. This way we prevent notifications although no observers are
|
|
// present.
|
|
static void ConnectToEmitters(const internal::DispatchData& dispatch_data) {
|
|
#if BUILDFLAG(USE_ALLOCATOR_SHIM)
|
|
if (auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch()) {
|
|
allocator_shim::InsertAllocatorDispatch(allocator_dispatch);
|
|
}
|
|
#endif
|
|
|
|
#if BUILDFLAG(USE_PARTITION_ALLOC)
|
|
{
|
|
auto* const allocation_hook = dispatch_data.GetAllocationObserverHook();
|
|
auto* const free_hook = dispatch_data.GetFreeObserverHook();
|
|
if (allocation_hook && free_hook) {
|
|
partition_alloc::PartitionAllocHooks::SetObserverHooks(allocation_hook,
|
|
free_hook);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void DisconnectFromEmitters(internal::DispatchData& dispatch_data) {
|
|
#if BUILDFLAG(USE_ALLOCATOR_SHIM)
|
|
if (auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch()) {
|
|
allocator_shim::RemoveAllocatorDispatchForTesting(
|
|
allocator_dispatch); // IN-TEST
|
|
}
|
|
#endif
|
|
|
|
#if BUILDFLAG(USE_PARTITION_ALLOC)
|
|
partition_alloc::PartitionAllocHooks::SetObserverHooks(nullptr, nullptr);
|
|
#endif
|
|
}
|
|
|
|
// Information on the hooks.
|
|
internal::DispatchData dispatch_data_;
|
|
#if DCHECK_IS_ON()
|
|
// Indicator if the dispatcher has been initialized before.
|
|
#if !defined(__cpp_lib_atomic_value_initialization) || \
|
|
__cpp_lib_atomic_value_initialization < 201911L
|
|
std::atomic_flag is_initialized_check_flag_ = ATOMIC_FLAG_INIT;
|
|
#else
|
|
std::atomic_flag is_initialized_check_flag_;
|
|
#endif
|
|
#endif
|
|
};
|
|
|
|
Dispatcher::Dispatcher() : impl_(std::make_unique<Impl>()) {}
|
|
|
|
Dispatcher::~Dispatcher() = default;
|
|
|
|
Dispatcher& Dispatcher::GetInstance() {
|
|
static base::NoDestructor<Dispatcher> instance;
|
|
return *instance;
|
|
}
|
|
|
|
void Dispatcher::Initialize(const internal::DispatchData& dispatch_data) {
|
|
impl_->Initialize(dispatch_data);
|
|
}
|
|
|
|
void Dispatcher::ResetForTesting() {
|
|
impl_->Reset();
|
|
}
|
|
} // namespace base::allocator::dispatcher
|