File indexing completed on 2024-12-15 05:02:06

0001 /*
0002     SPDX-FileCopyrightText: 2018 Ivan Čukić <ivan.cukic(at)kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #ifndef VOY_BASIC_DELAYED_H
0008 #define VOY_BASIC_DELAYED_H
0009 
0010 // STL
0011 #include <chrono>
0012 #include <optional>
0013 
0014 // Boost
0015 #include <boost/asio.hpp>
0016 
0017 // Self
0018 #include "../utils.h"
0019 #include "../traits.h"
0020 #include "../dsl/node_tags.h"
0021 #include "../dsl/node_traits.h"
0022 #include "../engine/asio/service.h"
0023 
0024 namespace voy {
0025 
0026 using voy::utils::non_copyable;
0027 
0028 using voy::dsl::continuator_base,
0029       voy::dsl::source_node_tag;
0030 
0031 namespace detail {
0032 
0033     template <typename T>
0034     class delayed_impl: non_copyable {
0035         voy_assert_value_type(T);
0036 
0037     public:
0038         using node_category = source_node_tag;
0039 
0040         explicit delayed_impl(std::chrono::milliseconds delay, std::initializer_list<T> c)
0041             : m_delay{delay}
0042             , m_values{c}
0043         {
0044         }
0045 
0046         template <typename C>
0047         explicit delayed_impl(std::chrono::milliseconds delay, C&& c)
0048             : m_delay{delay}
0049             , m_values{voy_fwd(c)}
0050         {
0051         }
0052 
0053         template <typename Cont>
0054         class node: public continuator_base<Cont>, non_copyable {
0055             using base = continuator_base<Cont>;
0056 
0057         public:
0058             using value_type = T;
0059 
0060             node(std::chrono::milliseconds delay, std::vector<T>&& values, Cont&& cont)
0061                 : base{std::move(cont)}
0062                 , m_delay{delay}
0063                 , m_values{std::move(values)}
0064             {
0065             }
0066 
0067             node(node&& other) = default;
0068 
0069             void init()
0070             {
0071                 base::init();
0072 
0073                 m_delay_timer = boost::asio::steady_timer(
0074                         engine::asio::service::instance(), m_delay);
0075 
0076                 m_delay_timer->async_wait([this] (const boost::system::error_code& e) {
0077                     for (auto&& value: m_values) {
0078                         base::emit(std::move(value));
0079                     }
0080 
0081                     m_values.clear();
0082 
0083                     base::notify_ended();
0084                 });
0085             }
0086 
0087         private:
0088             std::chrono::milliseconds m_delay;
0089             std::vector<T> m_values;
0090             std::optional<boost::asio::steady_timer> m_delay_timer;
0091         };
0092 
0093         template <typename Cont>
0094         auto with_continuation(Cont&& cont) &&
0095         {
0096             return node<Cont>(m_delay, std::move(m_values), voy_fwd(cont));
0097         }
0098 
0099     private:
0100         std::chrono::milliseconds m_delay;
0101         std::vector<T> m_values;
0102     };
0103 
0104 } // namespace detail
0105 
0106 template<typename T>
0107 decltype(auto) delayed(std::chrono::milliseconds delay, T&& value)
0108 {
0109     return detail::delayed_impl<T>(delay, {voy_fwd(value)});
0110 }
0111 
0112 template<typename T>
0113 decltype(auto) delayed_values(std::chrono::seconds delay, T&& values)
0114 {
0115     return detail::delayed_impl<typename T::value_type>(delay, voy_fwd(values));
0116 }
0117 
0118 template<typename T>
0119 decltype(auto) delayed_values(std::chrono::seconds delay, std::initializer_list<T> values)
0120 {
0121     return detail::delayed_impl<T>(delay, std::move(values));
0122 }
0123 
0124 
0125 } // namespace voy
0126 
0127 #endif // include guard
0128