ReactivePlusPlus
ReactiveX implementation for C++20
Loading...
Searching...
No Matches
fwd.hpp
1// ReactivePlusPlus library
2//
3// Copyright Aleksey Loginov 2023 - present.
4// Distributed under the Boost Software License, Version 1.0.
5// (See accompanying file LICENSE_1_0.txt or copy at
6// https://www.boost.org/LICENSE_1_0.txt)
7//
8// Project home: https://github.com/victimsnino/ReactivePlusPlus
9//
10
11#pragma once
12
13#include <rpp/disposables/fwd.hpp>
14
15#include <rpp/utils/constraints.hpp>
16
17#include <chrono>
18#include <optional>
19
20namespace rpp::schedulers
21{
22 using clock_type = std::chrono::steady_clock;
23 using time_point = clock_type::time_point;
24 using duration = std::chrono::nanoseconds;
25
36 {
37 explicit delay_from_now(duration duration = {})
38 : value{duration}
39 {
40 }
41
42 duration value;
43 };
44
57 {
58 explicit delay_from_this_timepoint(duration duration = {})
59 : value{duration}
60 {
61 }
62
63 duration value;
64 };
65
69 struct delay_to
70 {
71 explicit delay_to(time_point timepoint = {})
72 : value{timepoint}
73 {
74 }
75
76 time_point value;
77 };
78
79 using optional_delay_from_now = std::optional<delay_from_now>;
80 using optional_delay_from_this_timepoint = std::optional<delay_from_this_timepoint>;
81 using optional_delay_to = std::optional<delay_to>;
82} // namespace rpp::schedulers
83
84namespace rpp::schedulers::details
85{
87 {
88 constexpr static bool is_disposed() { return true; }
89
90 static void on_error(const std::exception_ptr&) {}
91 };
92} // namespace rpp::schedulers::details
93
94namespace rpp::schedulers::constraint
95{
96 // returns std::nullopt in case of don't need to re-schedule schedulable or some duration which will be added to "now" and re-scheduled
97 template<typename Fn, typename... Args>
98 concept schedulable_delay_from_now_fn = std::is_invocable_r_v<optional_delay_from_now, Fn, Args&...> && std::same_as<std::invoke_result_t<Fn, Args&...>, optional_delay_from_now>;
99
100 // returns std::nullopt in case of don't need to re-schedule schedulable or some duration which will be added to "now" and re-scheduled
101 template<typename Fn, typename... Args>
102 concept schedulable_delay_from_this_timepoint_fn = std::is_invocable_r_v<optional_delay_from_this_timepoint, Fn, Args&...> && std::same_as<std::invoke_result_t<Fn, Args&...>, optional_delay_from_this_timepoint>;
103
104 // returns std::nullopt in case of don't need to re-schedule schedulable or some duration which will be added to "now" and re-scheduled
105 template<typename Fn, typename... Args>
106 concept schedulable_delay_to_fn = std::is_invocable_r_v<optional_delay_to, Fn, Args&...> && std::same_as<std::invoke_result_t<Fn, Args&...>, optional_delay_to>;
107
108 // returns std::nullopt in case of don't need to re-schedule schedulable or one of `delay_from_now` or `delay_from_this_timepoint`
109 template<typename Fn, typename... Args>
111
112 template<typename Handler>
113 concept schedulable_handler = requires(const Handler& handler) {
114 {
115 handler.is_disposed()
116 } -> std::same_as<bool>;
117 handler.on_error(std::exception_ptr{});
118 };
119
120 template<typename S>
121 concept defer_for_strategy = requires(const S& s, const details::fake_schedulable_handler& handler) {
122 {
123 s.defer_for(duration{}, std::declval<optional_delay_from_now (*)(const details::fake_schedulable_handler&)>(), handler)
124 } -> std::same_as<void>;
125 {
126 s.defer_for(duration{}, std::declval<optional_delay_from_this_timepoint (*)(const details::fake_schedulable_handler&)>(), handler)
127 } -> std::same_as<void>;
128 {
129 s.defer_for(duration{}, std::declval<optional_delay_to (*)(const details::fake_schedulable_handler&)>(), handler)
130 } -> std::same_as<void>;
131 };
132
133 template<typename S>
134 concept defer_to_strategy = requires(const S& s, const details::fake_schedulable_handler& handler) {
135 {
136 s.defer_to(time_point{}, std::declval<optional_delay_from_now (*)(const details::fake_schedulable_handler&)>(), handler)
137 } -> std::same_as<void>;
138 {
139 s.defer_to(time_point{}, std::declval<optional_delay_from_this_timepoint (*)(const details::fake_schedulable_handler&)>(), handler)
140 } -> std::same_as<void>;
141 {
142 s.defer_to(time_point{}, std::declval<optional_delay_to (*)(const details::fake_schedulable_handler&)>(), handler)
143 } -> std::same_as<void>;
144 };
145
146 template<typename S>
148 {
149 S::now()
150 } -> std::same_as<rpp::schedulers::time_point>;
151 };
152} // namespace rpp::schedulers::constraint
153
154namespace rpp::schedulers
155{
156 template<rpp::schedulers::constraint::strategy Strategy>
157 class worker;
158
159 class immediate;
160 class current_thread;
161 class new_thread;
162 class run_loop;
163 class thread_pool;
164 class computational;
165
166 namespace defaults
167 {
168 using iteration_scheduler = current_thread;
169 } // namespace defaults
170} // namespace rpp::schedulers
171
172namespace rpp::schedulers::constraint
173{
174 namespace details
175 {
176 template<typename T>
177 struct is_worker : std::false_type
178 {
179 };
180
181 template<constraint::strategy Strategy>
182 struct is_worker<rpp::schedulers::worker<Strategy>> : std::true_type
183 {
184 };
185 } // namespace details
186
187 template<typename W>
188 concept worker = details::is_worker<W>::value;
189
190 template<typename S>
191 concept scheduler = requires(const S& s) {
192 {
193 s.create_worker()
194 } -> worker;
195 };
196} // namespace rpp::schedulers::constraint
197
198namespace rpp::schedulers::utils
199{
200 template<rpp::schedulers::constraint::scheduler Scheduler>
201 using get_worker_t = std::decay_t<decltype(std::declval<Scheduler>().create_worker())>;
202} // namespace rpp::schedulers::utils
Scheduler owning static thread pool of workers and using "some" thread from this pool on create_worke...
Definition computational.hpp:30
Schedules execution of schedulables via queueing tasks to the caller thread with priority to time_poi...
Definition current_thread.hpp:86
immediately calls provided schedulable or waits for time_point (in the caller-thread)
Definition immediate.hpp:65
Scheduler which schedules invoking of schedulables to another thread via queueing tasks with priority...
Definition new_thread.hpp:31
scheduler which schedules execution via queueing tasks, but execution of tasks should be manually dis...
Definition run_loop.hpp:31
Scheduler owning static thread pool of workers and using "some" thread from this pool on create_worke...
Definition thread_pool.hpp:31
Definition fwd.hpp:157
Timepoint of next execution would be calculcated from NOW timpoint (time of returning from schedulabl...
Definition fwd.hpp:36
Timepoint of next execution would be calculcated from timepoint of current scheduling.
Definition fwd.hpp:57
Provide timepoint of next execution explicitly.
Definition fwd.hpp:70