1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
|
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sample_executor.h"
SampleExecutor::SampleExecutor()
: executor_thread_(SampleExecutor::ThreadLoop, this),
executor_(Cronet_Executor_CreateWith(SampleExecutor::Execute)) {
Cronet_Executor_SetClientContext(executor_, this);
}
SampleExecutor::~SampleExecutor() {
ShutdownExecutor();
Cronet_Executor_Destroy(executor_);
}
Cronet_ExecutorPtr SampleExecutor::GetExecutor() {
return executor_;
}
void SampleExecutor::ShutdownExecutor() {
// Break tasks loop.
{
std::lock_guard<std::mutex> lock(lock_);
stop_thread_loop_ = true;
}
task_available_.notify_one();
// Wait for executor thread.
executor_thread_.join();
}
void SampleExecutor::RunTasksInQueue() {
// Process runnables in |task_queue_|.
while (true) {
Cronet_RunnablePtr runnable = nullptr;
{
// Wait for a task to run or stop signal.
std::unique_lock<std::mutex> lock(lock_);
while (task_queue_.empty() && !stop_thread_loop_)
task_available_.wait(lock);
if (stop_thread_loop_)
break;
if (task_queue_.empty())
continue;
runnable = task_queue_.front();
task_queue_.pop();
}
Cronet_Runnable_Run(runnable);
Cronet_Runnable_Destroy(runnable);
}
// Delete remaining tasks.
std::queue<Cronet_RunnablePtr> tasks_to_destroy;
{
std::unique_lock<std::mutex> lock(lock_);
tasks_to_destroy.swap(task_queue_);
}
while (!tasks_to_destroy.empty()) {
Cronet_Runnable_Destroy(tasks_to_destroy.front());
tasks_to_destroy.pop();
}
}
/* static */
void SampleExecutor::ThreadLoop(SampleExecutor* executor) {
executor->RunTasksInQueue();
}
void SampleExecutor::Execute(Cronet_RunnablePtr runnable) {
{
std::lock_guard<std::mutex> lock(lock_);
if (!stop_thread_loop_) {
task_queue_.push(runnable);
runnable = nullptr;
}
}
if (runnable) {
Cronet_Runnable_Destroy(runnable);
} else {
task_available_.notify_one();
}
}
/* static */
void SampleExecutor::Execute(Cronet_ExecutorPtr self,
Cronet_RunnablePtr runnable) {
auto* executor =
static_cast<SampleExecutor*>(Cronet_Executor_GetClientContext(self));
executor->Execute(runnable);
}
|