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