1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef LIB_FIT_SINGLE_THREADED_EXECUTOR_H_
6 #define LIB_FIT_SINGLE_THREADED_EXECUTOR_H_
7 
8 #include <utility>
9 
10 #include "promise.h"
11 #include "scheduler.h"
12 
13 namespace fit {
14 
15 // A simple platform-independent single-threaded asynchronous task executor.
16 //
17 // This implementation is designed for use when writing simple single-threaded
18 // platform-independent applications.  It may be less efficient or provide
19 // fewer features than more specialized or platform-dependent executors.
20 //
21 // See documentation of |fit::promise| for more information.
22 class single_threaded_executor final : public executor {
23 public:
24     single_threaded_executor();
25 
26     // Destroys the executor along with all of its remaining scheduled tasks
27     // that have yet to complete.
28     ~single_threaded_executor() override;
29 
30     // Schedules a task for eventual execution by the executor.
31     //
32     // This method is thread-safe.
33     void schedule_task(pending_task task) override;
34 
35     // Runs all scheduled tasks (including additional tasks scheduled while
36     // they run) until none remain.
37     //
38     // This method is thread-safe but must only be called on at most one
39     // thread at a time.
40     void run();
41 
42     single_threaded_executor(const single_threaded_executor&) = delete;
43     single_threaded_executor(single_threaded_executor&&) = delete;
44     single_threaded_executor& operator=(const single_threaded_executor&) = delete;
45     single_threaded_executor& operator=(single_threaded_executor&&) = delete;
46 
47 private:
48     class dispatcher_impl;
49 
50     // The task context for tasks run by the executor.
51     class context_impl final : public context {
52     public:
53         explicit context_impl(single_threaded_executor* executor);
54         ~context_impl() override;
55 
56         single_threaded_executor* executor() const override;
57         suspended_task suspend_task() override;
58 
59     private:
60         single_threaded_executor* const executor_;
61     };
62 
63     context_impl context_;
64     dispatcher_impl* const dispatcher_;
65 };
66 
67 // Creates a new |fit::single_threaded_executor|, schedules a promise as a task,
68 // runs all of the executor's scheduled tasks until none remain, then returns
69 // the promise's result.
70 template <typename Continuation>
71 static typename promise_impl<Continuation>::result_type
run_single_threaded(promise_impl<Continuation> promise)72 run_single_threaded(promise_impl<Continuation> promise) {
73     using result_type = typename promise_impl<Continuation>::result_type;
74     single_threaded_executor exec;
75     result_type saved_result;
76     exec.schedule_task(promise.then([&saved_result](result_type result) {
77         saved_result = std::move(result);
78     }));
79     exec.run();
80     return saved_result;
81 }
82 
83 } // namespace fit
84 
85 #endif // LIB_FIT_SINGLE_THREADED_EXECUTOR_H_
86