blob: 24ffd9b9dc61b1ec20c1faa096eb8a99df662ff0 [file] [log] [blame]
// Copyright 2019 The Chromium OS 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 "diagnostics/dpsl/internal/test_dpsl_background_thread.h"
#include <base/bind.h>
#include <base/location.h>
#include <base/logging.h>
#include "base/memory/scoped_refptr.h"
#include <base/run_loop.h>
#include <base/task_runner.h>
#include <base/threading/thread_task_runner_handle.h>
#include "diagnostics/dpsl/public/dpsl_global_context.h"
#include "diagnostics/dpsl/public/dpsl_thread_context.h"
namespace diagnostics {
// static
std::function<void()> TestDpslBackgroundThread::WrapTaskToReplyOnMainThread(
const base::Closure& background_callback,
DpslThreadContext* main_thread_context,
const base::Closure& main_thread_callback) {
DCHECK(main_thread_context);
DCHECK(!main_thread_callback.is_null());
return [background_callback, main_thread_context, main_thread_callback]() {
if (!background_callback.is_null()) {
background_callback.Run();
}
main_thread_context->PostTask(
[main_thread_callback]() { main_thread_callback.Run(); });
};
}
TestDpslBackgroundThread::TestDpslBackgroundThread(
const std::string& name,
DpslGlobalContext* global_context,
DpslThreadContext* main_thread_context)
: global_context_(global_context),
main_thread_context_(main_thread_context),
run_event_loop_event_(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED),
thread_(this, name) {
DCHECK(global_context);
DCHECK(main_thread_context_);
DCHECK(main_thread_context_->BelongsToCurrentThread());
base::RunLoop run_loop;
on_thread_context_ready_ = WrapTaskToReplyOnMainThread(
base::Closure(), main_thread_context_, run_loop.QuitClosure());
thread_.Start();
run_loop.Run();
}
TestDpslBackgroundThread::~TestDpslBackgroundThread() {
DCHECK(main_thread_context_->BelongsToCurrentThread());
run_event_loop_event_.Signal();
DoSync(base::Bind(
[](DpslThreadContext* background_thread_context) {
background_thread_context->QuitEventLoop();
},
thread_context_.get()));
thread_.Join();
}
void TestDpslBackgroundThread::StartEventLoop() {
DCHECK(!run_event_loop_event_.IsSignaled());
run_event_loop_event_.Signal();
}
void TestDpslBackgroundThread::DoSync(
const base::Closure& background_callback) {
DCHECK(run_event_loop_event_.IsSignaled());
DCHECK(main_thread_context_->BelongsToCurrentThread());
DCHECK(thread_context_);
base::RunLoop run_loop;
thread_context_->PostTask(WrapTaskToReplyOnMainThread(
background_callback, main_thread_context_, run_loop.QuitClosure()));
run_loop.Run();
}
DpslThreadContext* TestDpslBackgroundThread::thread_context() {
DCHECK(main_thread_context_->BelongsToCurrentThread());
return thread_context_.get();
}
void TestDpslBackgroundThread::Run() {
thread_context_ = DpslThreadContext::Create(global_context_);
DCHECK(thread_context_);
on_thread_context_ready_();
run_event_loop_event_.Wait();
thread_context_->RunEventLoop();
thread_context_.reset();
}
} // namespace diagnostics