Commit e70150fb authored by bashi's avatar bashi Committed by Commit bot

Move memory_coordinator_client and its registry to base/memory

This is the first CL to move memory_coordinator outside components/.
Also, per discussion on [1], this CL removes MemoryCoordinatorClient
from HistoryBackend. We can re-add it if needed.

[1] https://codereview.chromium.org/2297243004/#msg14

BUG=644022

Review-Url: https://codereview.chromium.org/2311723002
Cr-Commit-Position: refs/heads/master@{#418766}
parent 4bd1a1b4
......@@ -468,6 +468,9 @@ component("base") {
"memory/free_deleter.h",
"memory/linked_ptr.h",
"memory/manual_constructor.h",
"memory/memory_coordinator_client.h",
"memory/memory_coordinator_client_registry.cc",
"memory/memory_coordinator_client_registry.h",
"memory/memory_pressure_listener.cc",
"memory/memory_pressure_listener.h",
"memory/memory_pressure_monitor.cc",
......
......@@ -2,18 +2,30 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEMORY_COORDINATOR_COMMON_MEMORY_COORDINATOR_CLIENT_H_
#define MEMORY_COORDINATOR_COMMON_MEMORY_COORDINATOR_CLIENT_H_
#include "components/memory_coordinator/public/interfaces/child_memory_coordinator.mojom.h"
namespace memory_coordinator {
using MemoryState = mojom::MemoryState;
#ifndef BASE_MEMORY_MEMORY_COORDINATOR_CLIENT_H_
#define BASE_MEMORY_MEMORY_COORDINATOR_CLIENT_H_
#include "base/base_export.h"
namespace base {
// MemoryState is an indicator that processes can use to guide their memory
// allocation policies. For example, a process that receives the suspended
// state can use that as as signal to drop memory caches.
enum class MemoryState {
// The state is unknown.
UNKNOWN = -1,
// No memory constraints.
NORMAL = 0,
// Running and interactive but allocation should be throttled.
THROTTLED = 1,
// Still resident in memory but core processing logic has been suspended.
SUSPENDED = 2,
};
// This is an interface for components which can respond to memory status
// changes.
class MemoryCoordinatorClient {
class BASE_EXPORT MemoryCoordinatorClient {
public:
virtual ~MemoryCoordinatorClient() {}
......@@ -21,6 +33,6 @@ class MemoryCoordinatorClient {
virtual void OnMemoryStateChange(MemoryState state) = 0;
};
} // namespace memory_coordinator
} // namespace base
#endif // MEMORY_COORDINATOR_COMMON_MEMORY_COORDINATOR_CLIENT_H_
#endif // BASE_MEMORY_MEMORY_COORDINATOR_CLIENT_H_
// Copyright 2016 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.
#include "base/memory/memory_coordinator_client_registry.h"
namespace base {
// static
MemoryCoordinatorClientRegistry*
MemoryCoordinatorClientRegistry::GetInstance() {
return Singleton<
MemoryCoordinatorClientRegistry,
LeakySingletonTraits<MemoryCoordinatorClientRegistry>>::get();
}
MemoryCoordinatorClientRegistry::MemoryCoordinatorClientRegistry()
: clients_(new ClientList) {}
MemoryCoordinatorClientRegistry::~MemoryCoordinatorClientRegistry() {}
void MemoryCoordinatorClientRegistry::Register(
MemoryCoordinatorClient* client) {
clients_->AddObserver(client);
}
void MemoryCoordinatorClientRegistry::Unregister(
MemoryCoordinatorClient* client) {
clients_->RemoveObserver(client);
}
} // namespace base
......@@ -2,34 +2,40 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_MEMORY_COORDINATOR_COMMON_CLIENT_REGISTRY_H_
#define COMPONENTS_MEMORY_COORDINATOR_COMMON_CLIENT_REGISTRY_H_
#ifndef BASE_MEMORY_MEMORY_CLIENT_REGISTRY_H_
#define BASE_MEMORY_MEMORY_CLIENT_REGISTRY_H_
#include "base/base_export.h"
#include "base/memory/memory_coordinator_client.h"
#include "base/memory/singleton.h"
#include "base/observer_list_threadsafe.h"
#include "components/memory_coordinator/common/memory_coordinator_client.h"
#include "components/memory_coordinator/common/memory_coordinator_export.h"
namespace memory_coordinator {
namespace base {
// ClientRegistry is a base class of process-specific memory coordinator
// and provides ways to register/unregister MemoryCoordinatorClients.
class MEMORY_COORDINATOR_EXPORT ClientRegistry {
// MemoryCoordinatorClientRegistry is the registry for
// MemoryCoordinatorClients. Callbacks of MemoryCoordinatorClient are called
// via MemoryCoordinator.
class BASE_EXPORT MemoryCoordinatorClientRegistry {
public:
ClientRegistry();
virtual ~ClientRegistry();
static MemoryCoordinatorClientRegistry* GetInstance();
~MemoryCoordinatorClientRegistry();
// Registers/unregisters a client. Does not take ownership of client.
void RegisterClient(MemoryCoordinatorClient* client);
void UnregisterClient(MemoryCoordinatorClient* client);
void Register(MemoryCoordinatorClient* client);
void Unregister(MemoryCoordinatorClient* client);
protected:
using ClientList = base::ObserverListThreadSafe<MemoryCoordinatorClient>;
using ClientList = ObserverListThreadSafe<MemoryCoordinatorClient>;
ClientList* clients() { return clients_.get(); }
private:
friend struct DefaultSingletonTraits<MemoryCoordinatorClientRegistry>;
MemoryCoordinatorClientRegistry();
scoped_refptr<ClientList> clients_;
};
} // namespace memory_coordinator
} // namespace base
#endif // COMPONENTS_MEMORY_COORDINATOR_COMMON_CLIENT_REGISTRY_H_
#endif // BASE_MEMORY_MEMORY_CLIENT_REGISTRY_H_
......@@ -3,6 +3,5 @@ include_rules = [
"-components/history/content",
"-content",
"+components/memory_coordinator",
"+components/url_formatter",
]
......@@ -95,7 +95,6 @@ static_library("browser") {
"//components/favicon_base",
"//components/history/core/common",
"//components/keyed_service/core",
"//components/memory_coordinator/browser",
"//components/prefs",
"//components/query_parser",
"//components/signin/core/browser",
......
......@@ -41,7 +41,6 @@
#include "components/history/core/browser/page_usage_data.h"
#include "components/history/core/browser/typed_url_syncable_service.h"
#include "components/history/core/browser/url_utils.h"
#include "components/memory_coordinator/browser/memory_coordinator.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "sql/error_delegate_util.h"
#include "third_party/skia/include/core/SkBitmap.h"
......@@ -237,11 +236,6 @@ HistoryBackend::~HistoryBackend() {
FROM_HERE, backend_destroy_task_);
}
if (memory_coordinator::MemoryCoordinator::GetInstance()) {
memory_coordinator::MemoryCoordinator::GetInstance()->UnregisterClient(
this);
}
#if defined(OS_ANDROID)
if (backend_client_ && !history_dir_.empty())
backend_client_->OnHistoryBackendDestroyed(this, history_dir_);
......@@ -260,12 +254,8 @@ void HistoryBackend::Init(
InitImpl(history_database_params);
delegate_->DBLoaded();
typed_url_syncable_service_.reset(new TypedUrlSyncableService(this));
if (memory_coordinator::MemoryCoordinator::GetInstance()) {
memory_coordinator::MemoryCoordinator::GetInstance()->RegisterClient(this);
} else {
memory_pressure_listener_.reset(new base::MemoryPressureListener(
base::Bind(&HistoryBackend::OnMemoryPressure, base::Unretained(this))));
}
memory_pressure_listener_.reset(new base::MemoryPressureListener(
base::Bind(&HistoryBackend::OnMemoryPressure, base::Unretained(this))));
}
void HistoryBackend::SetOnBackendDestroyTask(base::MessageLoop* message_loop,
......@@ -749,19 +739,15 @@ void HistoryBackend::InitImpl(
LOCAL_HISTOGRAM_TIMES("History.InitTime", TimeTicks::Now() - beginning_time);
}
void HistoryBackend::TrimMemory(bool trim_aggressively) {
if (db_)
db_->TrimMemory(trim_aggressively);
if (thumbnail_db_)
thumbnail_db_->TrimMemory(trim_aggressively);
}
void HistoryBackend::OnMemoryPressure(
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
bool trim_aggressively =
memory_pressure_level ==
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
TrimMemory(trim_aggressively);
if (db_)
db_->TrimMemory(trim_aggressively);
if (thumbnail_db_)
thumbnail_db_->TrimMemory(trim_aggressively);
}
void HistoryBackend::CloseAllDatabases() {
......@@ -921,12 +907,6 @@ bool HistoryBackend::IsExpiredVisitTime(const base::Time& time) {
return time < expirer_.GetCurrentExpirationTime();
}
void HistoryBackend::OnMemoryStateChange(
memory_coordinator::MemoryState state) {
bool trim_aggressively = state == memory_coordinator::MemoryState::SUSPENDED;
TrimMemory(trim_aggressively);
}
void HistoryBackend::SetPageTitle(const GURL& url,
const base::string16& title) {
if (!db_)
......
......@@ -32,7 +32,6 @@
#include "components/history/core/browser/keyword_id.h"
#include "components/history/core/browser/thumbnail_database.h"
#include "components/history/core/browser/visit_tracker.h"
#include "components/memory_coordinator/common/memory_coordinator_client.h"
#include "sql/init_status.h"
class HistoryURLProvider;
......@@ -103,8 +102,7 @@ class QueuedHistoryDBTask {
// functions in the history service. These functions are not documented
// here, see the history service for behavior.
class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
public HistoryBackendNotifier,
public memory_coordinator::MemoryCoordinatorClient {
public HistoryBackendNotifier {
public:
// Interface implemented by the owner of the HistoryBackend object. Normally,
// the history service implements this to send stuff back to the main thread.
......@@ -480,9 +478,6 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
base::Time GetFirstRecordedTimeForTest() { return first_recorded_time_; }
// memory_coordinator::MemoryCoordinatorClient implementation:
void OnMemoryStateChange(memory_coordinator::MemoryState state) override;
protected:
~HistoryBackend() override;
......@@ -584,9 +579,6 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
// Does the work of Init.
void InitImpl(const HistoryDatabaseParams& history_database_params);
// Asks database to trim memory.
void TrimMemory(bool trim_aggressively);
// Called when the system is under memory pressure.
void OnMemoryPressure(
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
......
......@@ -4,6 +4,7 @@
#include "components/memory_coordinator/browser/memory_coordinator.h"
#include "base/memory/memory_coordinator_client_registry.h"
#include "components/memory_coordinator/common/memory_coordinator_features.h"
namespace memory_coordinator {
......
......@@ -5,9 +5,9 @@
#ifndef COMPONENTS_MEMORY_COORDINATOR_BROWSER_MEMORY_COORDINATOR_H_
#define COMPONENTS_MEMORY_COORDINATOR_BROWSER_MEMORY_COORDINATOR_H_
#include "base/memory/memory_coordinator_client_registry.h"
#include "base/memory/singleton.h"
#include "base/process/process_handle.h"
#include "components/memory_coordinator/common/client_registry.h"
#include "components/memory_coordinator/common/memory_coordinator_export.h"
#include "components/memory_coordinator/public/interfaces/memory_coordinator.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
......@@ -19,9 +19,9 @@ class MemoryCoordinatorHandleImpl;
// MemoryCoordinator is responsible for the whole memory management accross the
// browser and child proceeses. It dispatches memory events to its clients and
// child processes based on its best knowledge of the memory usage.
class MEMORY_COORDINATOR_EXPORT MemoryCoordinator : public ClientRegistry {
class MEMORY_COORDINATOR_EXPORT MemoryCoordinator {
public:
~MemoryCoordinator() override;
~MemoryCoordinator();
// Singleton factory/accessor.
static MemoryCoordinator* GetInstance();
......
......@@ -60,7 +60,7 @@ class TestMemoryCoordinator : public MemoryCoordinator {
};
TestMemoryCoordinator() {}
~TestMemoryCoordinator() override {}
~TestMemoryCoordinator() {}
using MemoryCoordinator::OnConnectionError;
......
......@@ -5,6 +5,7 @@
#include "components/memory_coordinator/child/child_memory_coordinator_impl.h"
#include "base/lazy_instance.h"
#include "base/memory/memory_coordinator_client_registry.h"
#include "base/synchronization/lock.h"
namespace memory_coordinator {
......@@ -14,6 +15,22 @@ namespace {
base::LazyInstance<base::Lock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER;
ChildMemoryCoordinatorImpl* g_child_memory_coordinator = nullptr;
base::MemoryState ToBaseMemoryState(mojom::MemoryState state) {
switch (state) {
case mojom::MemoryState::UNKNOWN:
return base::MemoryState::UNKNOWN;
case mojom::MemoryState::NORMAL:
return base::MemoryState::NORMAL;
case mojom::MemoryState::THROTTLED:
return base::MemoryState::THROTTLED;
case mojom::MemoryState::SUSPENDED:
return base::MemoryState::SUSPENDED;
default:
NOTREACHED();
return base::MemoryState::UNKNOWN;
}
}
} // namespace
// static
......@@ -40,8 +57,10 @@ ChildMemoryCoordinatorImpl::~ChildMemoryCoordinatorImpl() {
}
void ChildMemoryCoordinatorImpl::OnStateChange(mojom::MemoryState state) {
clients()->Notify(FROM_HERE, &MemoryCoordinatorClient::OnMemoryStateChange,
state);
base::MemoryState base_state = ToBaseMemoryState(state);
base::MemoryCoordinatorClientRegistry::GetInstance()->clients()->Notify(
FROM_HERE, &base::MemoryCoordinatorClient::OnMemoryStateChange,
base_state);
}
#if !defined(OS_ANDROID)
......
......@@ -6,8 +6,7 @@
#define COMPONENTS_MEMORY_COORDINATOR_CHILD_CHILD_MEMORY_COORDINATOR_IMPL_H_
#include "base/compiler_specific.h"
#include "components/memory_coordinator/common/client_registry.h"
#include "components/memory_coordinator/common/memory_coordinator_client.h"
#include "base/memory/memory_coordinator_client.h"
#include "components/memory_coordinator/common/memory_coordinator_export.h"
#include "components/memory_coordinator/common/memory_coordinator_features.h"
#include "components/memory_coordinator/public/interfaces/child_memory_coordinator.mojom.h"
......@@ -28,8 +27,7 @@ class MEMORY_COORDINATOR_EXPORT ChildMemoryCoordinatorDelegate {
// It lives in child processes and is responsible for dispatching memory events
// to its clients.
class MEMORY_COORDINATOR_EXPORT ChildMemoryCoordinatorImpl
: public ClientRegistry,
NON_EXPORTED_BASE(public mojom::ChildMemoryCoordinator) {
: NON_EXPORTED_BASE(public mojom::ChildMemoryCoordinator) {
public:
// Returns the instance of ChildMemoryCoordinatorImpl. Could be nullptr.
static ChildMemoryCoordinatorImpl* GetInstance();
......
......@@ -10,6 +10,7 @@
#include <memory>
#include "base/memory/memory_coordinator_client_registry.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/threading/thread.h"
......@@ -50,12 +51,12 @@ class ChildMemoryCoordinatorImplTest : public testing::Test,
loop.RunUntilIdle();
}
void RegisterClient(MemoryCoordinatorClient* client) {
coordinator_impl_->RegisterClient(client);
void RegisterClient(base::MemoryCoordinatorClient* client) {
base::MemoryCoordinatorClientRegistry::GetInstance()->Register(client);
}
void UnregisterClient(MemoryCoordinatorClient* client) {
coordinator_impl_->UnregisterClient(client);
void UnregisterClient(base::MemoryCoordinatorClient* client) {
base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(client);
}
mojom::ChildMemoryCoordinatorPtr& coordinator() {
......@@ -90,37 +91,36 @@ class ChildMemoryCoordinatorImplTest : public testing::Test,
namespace {
class MockMemoryCoordinatorClient final : public MemoryCoordinatorClient {
class MockMemoryCoordinatorClient final : public base::MemoryCoordinatorClient {
public:
void OnMemoryStateChange(mojom::MemoryState state) override {
void OnMemoryStateChange(base::MemoryState state) override {
last_state_ = state;
}
mojom::MemoryState last_state() const { return last_state_; }
base::MemoryState last_state() const { return last_state_; }
private:
mojom::MemoryState last_state_ = mojom::MemoryState::UNKNOWN;
base::MemoryState last_state_ = base::MemoryState::UNKNOWN;
};
class MemoryCoordinatorTestThread : public base::Thread,
public MemoryCoordinatorClient {
public base::MemoryCoordinatorClient {
public:
MemoryCoordinatorTestThread(
const std::string& name,
ChildMemoryCoordinatorImpl& coordinator)
: Thread(name), coordinator_(coordinator) {}
const std::string& name)
: Thread(name) {}
~MemoryCoordinatorTestThread() override { Stop(); }
void Init() override {
coordinator_.RegisterClient(this);
base::MemoryCoordinatorClientRegistry::GetInstance()->Register(this);
}
void OnMemoryStateChange(mojom::MemoryState state) override {
void OnMemoryStateChange(base::MemoryState state) override {
EXPECT_EQ(message_loop(), base::MessageLoop::current());
last_state_ = state;
}
void CheckLastState(mojom::MemoryState state) {
void CheckLastState(base::MemoryState state) {
task_runner()->PostTask(
FROM_HERE,
base::Bind(&MemoryCoordinatorTestThread::CheckLastStateInternal,
......@@ -128,14 +128,13 @@ class MemoryCoordinatorTestThread : public base::Thread,
}
private:
void CheckLastStateInternal(mojom::MemoryState state) {
void CheckLastStateInternal(base::MemoryState state) {
base::RunLoop loop;
loop.RunUntilIdle();
EXPECT_EQ(state, last_state_);
}
ChildMemoryCoordinatorImpl& coordinator_;
mojom::MemoryState last_state_ = mojom::MemoryState::UNKNOWN;
base::MemoryState last_state_ = base::MemoryState::UNKNOWN;
};
TEST_F(ChildMemoryCoordinatorImplTest, SingleClient) {
......@@ -143,30 +142,30 @@ TEST_F(ChildMemoryCoordinatorImplTest, SingleClient) {
RegisterClient(&client);
ChangeState(mojom::MemoryState::THROTTLED);
EXPECT_EQ(mojom::MemoryState::THROTTLED, client.last_state());
EXPECT_EQ(base::MemoryState::THROTTLED, client.last_state());
ChangeState(mojom::MemoryState::NORMAL);
EXPECT_EQ(mojom::MemoryState::NORMAL, client.last_state());
EXPECT_EQ(base::MemoryState::NORMAL, client.last_state());
UnregisterClient(&client);
ChangeState(mojom::MemoryState::THROTTLED);
EXPECT_TRUE(mojom::MemoryState::THROTTLED != client.last_state());
EXPECT_TRUE(base::MemoryState::THROTTLED != client.last_state());
}
TEST_F(ChildMemoryCoordinatorImplTest, MultipleClients) {
MemoryCoordinatorTestThread t1("thread 1", coordinator_impl());
MemoryCoordinatorTestThread t2("thread 2", coordinator_impl());
MemoryCoordinatorTestThread t1("thread 1");
MemoryCoordinatorTestThread t2("thread 2");
t1.StartAndWaitForTesting();
t2.StartAndWaitForTesting();
ChangeState(mojom::MemoryState::THROTTLED);
t1.CheckLastState(mojom::MemoryState::THROTTLED);
t2.CheckLastState(mojom::MemoryState::THROTTLED);
t1.CheckLastState(base::MemoryState::THROTTLED);
t2.CheckLastState(base::MemoryState::THROTTLED);
ChangeState(mojom::MemoryState::NORMAL);
t1.CheckLastState(mojom::MemoryState::NORMAL);
t2.CheckLastState(mojom::MemoryState::NORMAL);
t1.CheckLastState(base::MemoryState::NORMAL);
t2.CheckLastState(base::MemoryState::NORMAL);
t1.Stop();
t2.Stop();
......
......@@ -6,9 +6,6 @@ component("common") {
output_name = "memory_coordinator_common"
sources = [
"client_registry.cc",
"client_registry.h",
"memory_coordinator_client.h",
"memory_coordinator_export.h",
"memory_coordinator_features.cc",
"memory_coordinator_features.h",
......
// Copyright 2016 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.
#include "components/memory_coordinator/common/client_registry.h"
namespace memory_coordinator {
ClientRegistry::ClientRegistry() : clients_(new ClientList) {}
ClientRegistry::~ClientRegistry() {}
void ClientRegistry::RegisterClient(MemoryCoordinatorClient* client) {
clients_->AddObserver(client);
}
void ClientRegistry::UnregisterClient(MemoryCoordinatorClient* client) {
clients_->RemoveObserver(client);
}
} // namespace memory_coordinator
......@@ -4,17 +4,12 @@
module memory_coordinator.mojom;
// MemoryState is an indicator that processes can use to guide their memory
// allocation policies. For example, a process that receives the suspended
// state can use that as as signal to drop memory caches.
// See base/memory/memory_coordinator_client.h for the definitions of these
// states.
enum MemoryState {
// The state is unknown.
UNKNOWN = -1,
// No memory constraints.
NORMAL = 0,
// Running and interactive but allocation should be throttled.
THROTTLED = 1,
// Still resident in memory but core processing logic has been suspended.
SUSPENDED = 2,
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment