File indexing completed on 2024-06-16 05:06:54
0001 /* 0002 SPDX-FileCopyrightText: 2019 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_DEBOUNCE_H 0008 #define VOY_DEBOUNCE_H 0009 0010 // STL 0011 #include <chrono> 0012 #include <optional> 0013 #include <iostream> 0014 0015 // Boost 0016 #include <boost/asio.hpp> 0017 0018 // Self 0019 #include "../utils.h" 0020 #include "../traits.h" 0021 #include "../dsl/node_tags.h" 0022 #include "../dsl/node_traits.h" 0023 #include "../engine/asio/service.h" 0024 0025 namespace voy { 0026 0027 using voy::utils::non_copyable; 0028 0029 using voy::dsl::continuator_base, 0030 voy::dsl::transformation_node_tag; 0031 0032 namespace detail { 0033 0034 template <typename T> 0035 class debounce_impl: non_copyable { 0036 voy_assert_value_type(T); 0037 0038 public: 0039 using node_category = transformation_node_tag; 0040 0041 explicit debounce_impl(std::chrono::milliseconds delay) 0042 : m_delay{delay} 0043 { 0044 } 0045 0046 template <typename Cont> 0047 class node: public continuator_base<Cont>, non_copyable { 0048 using base = continuator_base<Cont>; 0049 0050 public: 0051 node(std::chrono::milliseconds delay, Cont&& cont) 0052 : base{std::move(cont)} 0053 , m_delay{delay} 0054 { 0055 } 0056 0057 // node(node&& other) = default; 0058 node(node&& other) noexcept 0059 : base{std::move(other)} 0060 , m_delay{other.m_delay} 0061 { 0062 } 0063 0064 void init() 0065 { 0066 base::init(); 0067 0068 m_delay_timer = boost::asio::steady_timer( 0069 engine::asio::service::instance()); 0070 } 0071 0072 void operator() (T&& value) const 0073 { 0074 m_last_value = std::move(value); 0075 using namespace std::literals::chrono_literals; 0076 0077 m_delay_timer->expires_after(m_delay); 0078 m_delay_timer->async_wait([this] (const boost::system::error_code& error) { 0079 if (error) return; 0080 base::emit(std::move(m_last_value)); 0081 }); 0082 } 0083 0084 private: 0085 std::chrono::milliseconds m_delay; 0086 mutable std::optional<boost::asio::steady_timer> m_delay_timer; 0087 mutable T m_last_value; 0088 }; 0089 0090 template <typename Cont> 0091 auto with_continuation(Cont&& cont) && 0092 { 0093 return node<Cont>(m_delay, voy_fwd(cont)); 0094 } 0095 0096 private: 0097 std::chrono::milliseconds m_delay; 0098 }; 0099 0100 } // namespace detail 0101 0102 template<typename T> 0103 decltype(auto) debounce(std::chrono::milliseconds delay) 0104 { 0105 return detail::debounce_impl<T>(delay); 0106 } 0107 0108 } // namespace voy 0109 0110 #endif // include guard 0111