blob: a033b8e89c5d2fc54246c7558ac4272dbc585659 [file] [log] [blame]
// Copyright 2018 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.
#ifndef SRC_LIB_FASYNC_INCLUDE_LIB_FASYNC_SINGLE_THREADED_EXECUTOR_H_
#define SRC_LIB_FASYNC_INCLUDE_LIB_FASYNC_SINGLE_THREADED_EXECUTOR_H_
#include <lib/fasync/future.h>
#include <lib/fasync/scheduler.h>
#include <lib/fit/thread_safety.h>
#include <utility>
namespace fasync {
// A simple platform-independent single-threaded asynchronous task executor.
//
// This implementation is designed for use when writing simple single-threaded platform-independent
// applications. It may be less efficient or provide fewer features than more specialized or
// platform-dependent executors.
//
// See documentation of |fasync::future| for more information.
class single_threaded_executor final : public executor {
public:
single_threaded_executor();
// Destroys the executor along with all of its remaining scheduled tasks that have yet to
// complete.
~single_threaded_executor() override;
// Schedules a task for eventual execution by the executor.
//
// This method is thread-safe.
void schedule(pending_task&& task) override;
// Runs all scheduled tasks (including additional tasks scheduled while they run) until none
// remain.
//
// This method is thread-safe but must only be called on at most one thread at a time.
void run();
single_threaded_executor(const single_threaded_executor&) = delete;
single_threaded_executor& operator=(const single_threaded_executor&) = delete;
single_threaded_executor(single_threaded_executor&&) = delete;
single_threaded_executor& operator=(single_threaded_executor&&) = delete;
private:
// The task context for tasks run by the executor.
class context_impl final : public context {
public:
explicit context_impl(single_threaded_executor& executor) : executor_(executor) {}
~context_impl() override = default;
single_threaded_executor& executor() const override { return executor_; }
suspended_task suspend_task() override;
private:
single_threaded_executor& executor_;
};
class dispatcher_impl;
context_impl context_;
dispatcher_impl* const dispatcher_;
};
namespace internal {
class block_closure final : future_adaptor_closure<block_closure> {
public:
template <typename E = single_threaded_executor, typename F,
requires_conditions<is_future<F>> = true>
std::conditional_t<is_void_future_v<F>, bool, cpp17::optional<future_output_t<F>>> operator()(
F&& future) const {
E executor;
return block_on(std::forward<F>(future), executor);
}
};
} // namespace internal
// |fasync::block|
//
// Creates a new |fasync::single_threaded_executor| (by default), schedules a future as a task,
// runs all of the executor's scheduled tasks until none remain, then returns
// the future's result.
//
// Call pattern:
// - fasync::block(<future>) -> std::optional<result> (or bool for void futures)
// - <future> | fasync::block -> std::optional<result> (or bool)
LIB_FASYNC_INLINE_CONSTANT constexpr ::fasync::internal::block_closure block;
} // namespace fasync
#endif // SRC_LIB_FASYNC_INCLUDE_LIB_FASYNC_SINGLE_THREADED_EXECUTOR_H_