| // Copyright 2020 The Fuchsia 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 <lib/synchronous-executor/executor.h> | |
| #include <condition_variable> | |
| #include <mutex> | |
| namespace synchronous_executor { | |
| void synchronous_executor::schedule_task(fit::pending_task task) { | |
| std::lock_guard<std::mutex> lock(mutex_); | |
| scheduler_.schedule_task(std::move(task)); | |
| } | |
| void synchronous_executor::run_until_idle() { | |
| // Run until the queue is empty | |
| while (true) { | |
| fit::subtle::scheduler::task_queue queue; | |
| { | |
| std::lock_guard<std::mutex> lock(mutex_); | |
| scheduler_.take_runnable_tasks(&queue); | |
| } | |
| if (queue.empty()) { | |
| return; | |
| } | |
| while (!queue.empty()) { | |
| context_impl context(this); | |
| queue.front()(context); | |
| auto ticket = context.take_ticket(); | |
| if (ticket.has_value()) { | |
| std::lock_guard<std::mutex> lock(mutex_); | |
| scheduler_.finalize_ticket(ticket.value(), &queue.front()); | |
| } | |
| queue.pop(); | |
| } | |
| } | |
| } | |
| fit::suspended_task::ticket synchronous_executor::resolver_impl::duplicate_ticket( | |
| fit::suspended_task::ticket ticket) { | |
| std::lock_guard<std::mutex> lock(executor_->mutex_); | |
| executor_->scheduler_.duplicate_ticket(ticket); | |
| return ticket; | |
| } | |
| // Consumes the provided ticket, optionally resuming its associated task. | |
| // The provided ticket must not be used again. | |
| void synchronous_executor::resolver_impl::resolve_ticket(fit::suspended_task::ticket ticket, | |
| bool resume_task) { | |
| fit::pending_task task; | |
| { | |
| std::lock_guard<std::mutex> lock(executor_->mutex_); | |
| if (resume_task) { | |
| executor_->scheduler_.resume_task_with_ticket(ticket); | |
| } else { | |
| task = executor_->scheduler_.release_ticket(ticket); | |
| } | |
| } | |
| } | |
| synchronous_executor* synchronous_executor::context_impl::executor() const { return executor_; } | |
| fit::suspended_task synchronous_executor::context_impl::suspend_task() { | |
| std::lock_guard<std::mutex> lock(executor_->mutex_); | |
| // One ref for us, another for the promise itself | |
| ticket_ = executor_->scheduler_.obtain_ticket(2); | |
| return fit::suspended_task(&executor_->resolver_, ticket_.value()); | |
| } | |
| } // namespace synchronous_executor |