/* * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License Version 2.0 with LLVM Exceptions * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * https://llvm.org/LICENSE.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include #include #include #include #include #include namespace unifex { class timed_single_thread_context; namespace _timed_single_thread_context { using clock_t = std::chrono::steady_clock; using time_point = typename clock_t::time_point; struct task_base { using execute_fn = void(task_base*) noexcept; explicit task_base(timed_single_thread_context& context, execute_fn* execute) noexcept : context_(&context), execute_(execute) {} timed_single_thread_context* const context_; task_base* next_ = nullptr; task_base** prevNextPtr_ = nullptr; execute_fn* execute_; time_point dueTime_; void execute() noexcept { execute_(this); } }; class cancel_callback { task_base* const task_; public: explicit cancel_callback(task_base* task) noexcept : task_(task) {} void operator()() noexcept; }; class scheduler; template struct _schedule_after_sender { class type; }; template using schedule_after_sender = typename _schedule_after_sender::type; template struct _after_op { class type; }; template using after_operation = typename _after_op>::type; template class _after_op::type final : task_base { friend schedule_after_sender; template explicit type( timed_single_thread_context& context, Duration duration, Receiver2&& receiver) : task_base(context, &type::execute_impl), duration_(duration), receiver_((Receiver2 &&) receiver) { UNIFEX_ASSERT(context_ != nullptr); } static void execute_impl(task_base* t) noexcept { auto& self = *static_cast(t); self.cancelCallback_.destruct(); if constexpr (is_stop_never_possible_v< stop_token_type_t>) { unifex::set_value(static_cast(self.receiver_)); } else { if (get_stop_token(self.receiver_).stop_requested()) { unifex::set_done(static_cast(self.receiver_)); } else { unifex::set_value(static_cast(self.receiver_)); } } } Duration duration_; UNIFEX_NO_UNIQUE_ADDRESS Receiver receiver_; UNIFEX_NO_UNIQUE_ADDRESS manual_lifetime::template callback_type> cancelCallback_; public: void start() noexcept; }; template class _schedule_after_sender::type { friend scheduler; explicit type( timed_single_thread_context& context, Duration duration) noexcept : context_(&context), duration_(duration) {} timed_single_thread_context* context_; Duration duration_; public: template < template class Variant, template class Tuple> using value_types = Variant>; template