Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1012)

Unified Diff: content/browser/browser_main_loop.cc

Issue 2464233002: Experiment with redirecting all BrowserThreads (but UI/IO) to TaskScheduler (Closed)
Patch Set: Rely on Thread::using_external_message_loop_ instead of hard-coding BrowserThread::UI Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/browser_main_loop.cc
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index f4b7eae0ba294a5cd96d7e39655eff0555045ddd..eb274bb20e1653abcd8559ecc1856546a2d6338b 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -30,7 +30,10 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
+#include "base/synchronization/waitable_event.h"
#include "base/system_monitor/system_monitor.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/task_scheduler/task_traits.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/timer/hi_res_timer_manager.h"
@@ -298,38 +301,90 @@ void OnStoppedStartupTracing(const base::FilePath& trace_file) {
MSVC_DISABLE_OPTIMIZE()
MSVC_PUSH_DISABLE_WARNING(4748)
-NOINLINE void ResetThread_DB(std::unique_ptr<BrowserProcessSubThread> thread) {
+// Takes ownership of |task_runner| and blocks until it's empty.
+void FlushThreadTaskRunner(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ base::WaitableEvent thread_terminated(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ task_runner->PostTask(FROM_HERE,
+ base::Bind(&base::WaitableEvent::Signal,
+ base::Unretained(&thread_terminated)));
+ thread_terminated.Wait();
+}
+
+NOINLINE void ResetThread_DB(
+ std::unique_ptr<BrowserProcessSubThread> thread,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ DCHECK(!thread || !task_runner);
Avi (use Gerrit) 2016/11/08 16:16:15 This checks that we don't have both. Do we want t
gab 2016/11/08 20:40:44 Right, made this DCHECK((thread && !task_runner) |
volatile int inhibit_comdat = __LINE__;
ALLOW_UNUSED_LOCAL(inhibit_comdat);
- thread.reset();
+ if (thread) {
+ thread.reset();
+ } else {
+ BrowserThreadImpl::RedirectThreadIDToTaskRunner(BrowserThread::DB, nullptr);
+ FlushThreadTaskRunner(std::move(task_runner));
+ }
}
NOINLINE void ResetThread_FILE(
- std::unique_ptr<BrowserProcessSubThread> thread) {
+ std::unique_ptr<BrowserProcessSubThread> thread,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ DCHECK(!thread || !task_runner);
volatile int inhibit_comdat = __LINE__;
ALLOW_UNUSED_LOCAL(inhibit_comdat);
- thread.reset();
+ if (thread) {
+ thread.reset();
+ } else {
+ BrowserThreadImpl::RedirectThreadIDToTaskRunner(BrowserThread::FILE,
+ nullptr);
+ FlushThreadTaskRunner(std::move(task_runner));
+ }
}
NOINLINE void ResetThread_FILE_USER_BLOCKING(
- std::unique_ptr<BrowserProcessSubThread> thread) {
+ std::unique_ptr<BrowserProcessSubThread> thread,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ DCHECK(!thread || !task_runner);
volatile int inhibit_comdat = __LINE__;
ALLOW_UNUSED_LOCAL(inhibit_comdat);
- thread.reset();
+ if (thread) {
+ thread.reset();
+ } else {
+ BrowserThreadImpl::RedirectThreadIDToTaskRunner(
+ BrowserThread::FILE_USER_BLOCKING, nullptr);
+ FlushThreadTaskRunner(std::move(task_runner));
+ }
}
NOINLINE void ResetThread_PROCESS_LAUNCHER(
- std::unique_ptr<BrowserProcessSubThread> thread) {
+ std::unique_ptr<BrowserProcessSubThread> thread,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ DCHECK(!thread || !task_runner);
volatile int inhibit_comdat = __LINE__;
ALLOW_UNUSED_LOCAL(inhibit_comdat);
- thread.reset();
+ if (thread) {
+ thread.reset();
+ } else {
+ BrowserThreadImpl::RedirectThreadIDToTaskRunner(
+ BrowserThread::PROCESS_LAUNCHER, nullptr);
+ FlushThreadTaskRunner(std::move(task_runner));
+ }
}
NOINLINE void ResetThread_CACHE(
- std::unique_ptr<BrowserProcessSubThread> thread) {
+ std::unique_ptr<BrowserProcessSubThread> thread,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ DCHECK(!thread || !task_runner);
volatile int inhibit_comdat = __LINE__;
ALLOW_UNUSED_LOCAL(inhibit_comdat);
- thread.reset();
+ if (thread) {
+ thread.reset();
+ } else {
+ BrowserThreadImpl::RedirectThreadIDToTaskRunner(BrowserThread::CACHE,
+ nullptr);
+ FlushThreadTaskRunner(std::move(task_runner));
+ }
}
NOINLINE void ResetThread_IO(std::unique_ptr<BrowserProcessSubThread> thread) {
@@ -867,54 +922,120 @@ int BrowserMainLoop::CreateThreads() {
for (size_t thread_id = BrowserThread::UI + 1;
thread_id < BrowserThread::ID_COUNT;
++thread_id) {
- std::unique_ptr<BrowserProcessSubThread>* thread_to_start = NULL;
+ // If this thread ID is backed by a real thread, |thread_to_start| will be
+ // set to the appropriate |BrowserProcessSubThread*|. And |options| can be
+ // updated away from its default.
+ std::unique_ptr<BrowserProcessSubThread>* thread_to_start = nullptr;
base::Thread::Options options;
+ // Otherwise this thread ID will be backed by a SingleThreadTaskRunner in
+ // which case |task_runner_to_create| will be set to the appropriate
+ // |SingleThreadTaskRunner*| and |task_runner_traits| can be updated away
+ // from its default. |execution_mode| defaults to |SINGLE_THREADED| as-is
+ // appropriate to map most old browser threads but can also be updated in
+ // the switch statement below if a thread has specific requirements.
+ scoped_refptr<base::SingleThreadTaskRunner>* task_runner_to_create =
+ nullptr;
+ base::TaskTraits task_runner_traits;
+
+ const bool redirect_nonUInonIO_browser_threads =
+ GetContentClient()
+ ->browser()
+ ->RedirectNonUINonIOBrowserThreadsToTaskScheduler();
+
switch (thread_id) {
case BrowserThread::DB:
TRACE_EVENT_BEGIN1("startup",
"BrowserMainLoop::CreateThreads:start",
"Thread", "BrowserThread::DB");
- thread_to_start = &db_thread_;
- options.timer_slack = base::TIMER_SLACK_MAXIMUM;
+ if (redirect_nonUInonIO_browser_threads) {
+ task_runner_to_create = &db_task_runner_;
+ task_runner_traits.WithFileIO()
+ .WithPriority(base::TaskPriority::USER_VISIBLE)
+ .WithShutdownBehavior(base::TaskShutdownBehavior::BLOCK_SHUTDOWN);
+ } else {
+ thread_to_start = &db_thread_;
+ options.timer_slack = base::TIMER_SLACK_MAXIMUM;
+ }
break;
case BrowserThread::FILE_USER_BLOCKING:
TRACE_EVENT_BEGIN1("startup",
"BrowserMainLoop::CreateThreads:start",
"Thread", "BrowserThread::FILE_USER_BLOCKING");
- thread_to_start = &file_user_blocking_thread_;
+ if (redirect_nonUInonIO_browser_threads) {
+ task_runner_to_create = &file_user_blocking_task_runner_;
+ task_runner_traits.WithFileIO()
+ .WithPriority(base::TaskPriority::USER_BLOCKING)
+ .WithShutdownBehavior(base::TaskShutdownBehavior::BLOCK_SHUTDOWN);
+ } else {
+ thread_to_start = &file_user_blocking_thread_;
+ }
break;
case BrowserThread::FILE:
TRACE_EVENT_BEGIN1("startup",
"BrowserMainLoop::CreateThreads:start",
"Thread", "BrowserThread::FILE");
- thread_to_start = &file_thread_;
+
#if defined(OS_WIN)
- // On Windows, the FILE thread needs to be have a UI message loop
- // which pumps messages in such a way that Google Update can
- // communicate back to us.
+ // On Windows, the FILE thread needs to be have a UI message loop which
+ // pumps messages in such a way that Google Update can communicate back
+ // to us.
+ // TODO(robliao): Need to support COM in TaskScheduler before
+ // redirecting the FILE thread on Windows. http://crbug.com/662122
+ // TODO(gab): Also need to support clipboard (see below).
+ thread_to_start = &file_thread_;
options = ui_message_loop_options;
#else
- options = io_message_loop_options;
+ if (redirect_nonUInonIO_browser_threads) {
+ task_runner_to_create = &file_task_runner_;
+ task_runner_traits.WithFileIO()
+ .WithPriority(base::TaskPriority::BACKGROUND)
+ .WithShutdownBehavior(base::TaskShutdownBehavior::BLOCK_SHUTDOWN);
+ } else {
+ thread_to_start = &file_thread_;
+ options = io_message_loop_options;
+ options.timer_slack = base::TIMER_SLACK_MAXIMUM;
+ }
#endif
- options.timer_slack = base::TIMER_SLACK_MAXIMUM;
break;
case BrowserThread::PROCESS_LAUNCHER:
TRACE_EVENT_BEGIN1("startup",
"BrowserMainLoop::CreateThreads:start",
"Thread", "BrowserThread::PROCESS_LAUNCHER");
- thread_to_start = &process_launcher_thread_;
- options.timer_slack = base::TIMER_SLACK_MAXIMUM;
+ if (redirect_nonUInonIO_browser_threads) {
+ task_runner_to_create = &process_launcher_task_runner_;
+ task_runner_traits.WithFileIO()
+ .WithPriority(base::TaskPriority::USER_BLOCKING)
+ .WithShutdownBehavior(base::TaskShutdownBehavior::BLOCK_SHUTDOWN);
+ } else {
+ thread_to_start = &process_launcher_thread_;
+ options.timer_slack = base::TIMER_SLACK_MAXIMUM;
+ }
break;
case BrowserThread::CACHE:
TRACE_EVENT_BEGIN1("startup",
"BrowserMainLoop::CreateThreads:start",
"Thread", "BrowserThread::CACHE");
- thread_to_start = &cache_thread_;
#if defined(OS_WIN)
+ // TaskScheduler doesn't support async I/O on Windows as CACHE thread is
+ // the only user and this use case is going away in
+ // https://codereview.chromium.org/2216583003/. TODO(gavinp): Remove
+ // this ifdef (and thus enable redirection of the CACHE thread on
+ // Windows) once that CL lands.
+ thread_to_start = &cache_thread_;
options = io_message_loop_options;
-#endif // defined(OS_WIN)
options.timer_slack = base::TIMER_SLACK_MAXIMUM;
+#else // OS_WIN
+ if (redirect_nonUInonIO_browser_threads) {
+ task_runner_to_create = &cache_task_runner_;
+ task_runner_traits.WithFileIO()
+ .WithPriority(base::TaskPriority::USER_BLOCKING)
+ .WithShutdownBehavior(base::TaskShutdownBehavior::BLOCK_SHUTDOWN);
+ } else {
+ thread_to_start = &cache_thread_;
+ options.timer_slack = base::TIMER_SLACK_MAXIMUM;
+ }
+#endif // OS_WIN
break;
case BrowserThread::IO:
TRACE_EVENT_BEGIN1("startup",
@@ -928,9 +1049,8 @@ int BrowserMainLoop::CreateThreads() {
options.priority = base::ThreadPriority::DISPLAY;
#endif
break;
- case BrowserThread::UI:
- case BrowserThread::ID_COUNT:
- default:
+ case BrowserThread::UI: // Falls through.
+ case BrowserThread::ID_COUNT: // Falls through.
NOTREACHED();
break;
}
@@ -938,10 +1058,17 @@ int BrowserMainLoop::CreateThreads() {
BrowserThread::ID id = static_cast<BrowserThread::ID>(thread_id);
if (thread_to_start) {
+ DCHECK(!task_runner_to_create);
(*thread_to_start).reset(new BrowserProcessSubThread(id));
if (!(*thread_to_start)->StartWithOptions(options)) {
LOG(FATAL) << "Failed to start the browser thread: id == " << id;
}
+ } else if (task_runner_to_create) {
+ *task_runner_to_create =
+ base::CreateSingleThreadTaskRunnerWithTraits(task_runner_traits);
+ DCHECK(*task_runner_to_create);
+ BrowserThreadImpl::RedirectThreadIDToTaskRunner(
+ id, task_runner_to_create->get());
} else {
NOTREACHED();
}
@@ -1089,31 +1216,35 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
switch (thread_id) {
case BrowserThread::DB: {
TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:DBThread");
- ResetThread_DB(std::move(db_thread_));
+ ResetThread_DB(std::move(db_thread_), std::move(db_task_runner_));
break;
}
case BrowserThread::FILE: {
TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:FileThread");
- // Clean up state that lives on or uses the file_thread_ before
- // it goes away.
+ // Clean up state that lives on or uses the file_thread_ before it goes
+ // away.
save_file_manager_->Shutdown();
- ResetThread_FILE(std::move(file_thread_));
+ ResetThread_FILE(std::move(file_thread_), std::move(file_task_runner_));
break;
}
case BrowserThread::FILE_USER_BLOCKING: {
TRACE_EVENT0("shutdown",
"BrowserMainLoop::Subsystem:FileUserBlockingThread");
- ResetThread_FILE_USER_BLOCKING(std::move(file_user_blocking_thread_));
+ ResetThread_FILE_USER_BLOCKING(
+ std::move(file_user_blocking_thread_),
+ std::move(file_user_blocking_task_runner_));
break;
}
case BrowserThread::PROCESS_LAUNCHER: {
TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:LauncherThread");
- ResetThread_PROCESS_LAUNCHER(std::move(process_launcher_thread_));
+ ResetThread_PROCESS_LAUNCHER(std::move(process_launcher_thread_),
+ std::move(process_launcher_task_runner_));
break;
}
case BrowserThread::CACHE: {
TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:CacheThread");
- ResetThread_CACHE(std::move(cache_thread_));
+ ResetThread_CACHE(std::move(cache_thread_),
+ std::move(cache_task_runner_));
break;
}
case BrowserThread::IO: {
@@ -1123,7 +1254,6 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
}
case BrowserThread::UI:
case BrowserThread::ID_COUNT:
- default:
NOTREACHED();
break;
}
@@ -1361,6 +1491,8 @@ int BrowserMainLoop::BrowserThreadsStarted() {
allowed_clipboard_threads.push_back(base::PlatformThread::CurrentId());
#if defined(OS_WIN)
// On Windows, clipboards are also used on the FILE or IO threads.
+ // TODO(gab): Figure out how to selectively allow clipboard via TaskTraits for
+ // TaskScheduler. http://crbug.com/662055
allowed_clipboard_threads.push_back(file_thread_->GetThreadId());
allowed_clipboard_threads.push_back(io_thread_->GetThreadId());
#endif

Powered by Google App Engine
This is Rietveld 408576698