diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b396b5..d4c210e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,54 +1,55 @@ cmake_minimum_required (VERSION 3.11) project (lancelot) set (PROJECT_VERSION "0.1") set (PROJECT_VERSION_MAJOR 0) set (CMAKE_CXX_STANDARD 17) add_definitions (-fexceptions -pthread) if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") message (FATAL_ERROR "This project requires an out of source build") endif () include (FeatureSummary) find_package (ECM 5.46 NO_MODULE) set_package_properties (ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://projects.kde.org/projects/kdesupport/extra-cmake-modules") feature_summary (WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES) set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} ) include (KDEInstallDirs) include (KDECMakeSettings) # We can not live without Qt and Boost set (REQUIRED_QT_VERSION 5.10.0) find_package ( Qt5 REQUIRED COMPONENTS Gui Qml Quick ) find_package ( Boost 1.67 REQUIRED COMPONENTS system filesystem # asio and process are header-only ) +include_directories (${Boost_INCLUDE_DIR}) # Defining the sources add_subdirectory (src) diff --git a/src/voy/basic/delayed.h b/src/voy/basic/delayed.h new file mode 100644 index 0000000..c2cf3fe --- /dev/null +++ b/src/voy/basic/delayed.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2018 Ivan Čukić + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + * If not, see . + */ + +#ifndef VOY_BASIC_DELAYED_H +#define VOY_BASIC_DELAYED_H + +// STL +#include +#include + +// Boost +#include + +// Self +#include "../utils.h" +#include "../traits.h" +#include "../dsl/node_tags.h" +#include "../dsl/node_traits.h" +#include "../engine/asio/service.h" + +namespace voy { + +using voy::utils::non_copyable; + +using voy::dsl::continuator_base, + voy::dsl::source_node_tag; + +namespace detail { + + template + class delayed_impl: non_copyable { + voy_assert_value_type(T); + + public: + using node_category = source_node_tag; + + explicit delayed_impl(std::chrono::seconds delay, std::initializer_list c) + : m_delay{delay} + , m_values{c} + { + } + + template + explicit delayed_impl(std::chrono::seconds delay, C&& c) + : m_delay{delay} + , m_values{voy_fwd(c)} + { + } + + template + class node: continuator_base, non_copyable { + using base = continuator_base; + + public: + using value_type = T; + + node(std::chrono::seconds delay, std::vector&& values, Cont&& cont) + : base{std::move(cont)} + , m_delay{delay} + , m_values{std::move(values)} + { + } + + node(node&& other) = default; + + void init() + { + base::init(); + + m_delay_timer = boost::asio::steady_timer( + engine::asio::service::instance(), m_delay); + + m_delay_timer->async_wait([this] (const boost::system::error_code& e) { + for (auto&& value: m_values) { + base::emit(std::move(value)); + } + + base::notify_ended(); + }); + } + + private: + std::chrono::seconds m_delay; + std::vector m_values; + std::optional m_delay_timer; + }; + + template + auto with_continuation(Cont&& cont) && + { + return node(m_delay, std::move(m_values), voy_fwd(cont)); + } + + private: + std::chrono::seconds m_delay; + std::vector m_values; + }; + +} // namespace detail + +template +decltype(auto) delayed(std::chrono::seconds delay, T&& value) +{ + return detail::delayed_impl(delay, {voy_fwd(value)}); +} + +template +decltype(auto) delayed_values(std::chrono::seconds delay, T&& values) +{ + return detail::delayed_impl(delay, voy_fwd(values)); +} + +template +decltype(auto) delayed_values(std::chrono::seconds delay, std::initializer_list values) +{ + return detail::delayed_impl(delay, std::move(values)); +} + +} // namespace voy + +#endif // include guard + diff --git a/src/voy/basic/values.h b/src/voy/basic/values.h index 11e8471..2445a74 100644 --- a/src/voy/basic/values.h +++ b/src/voy/basic/values.h @@ -1,109 +1,109 @@ /* * Copyright (C) 2018 Ivan Čukić * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. * If not, see . */ #ifndef VOY_BASIC_VALUES_H #define VOY_BASIC_VALUES_H // STL #include #include #include // Self #include "../utils.h" #include "../traits.h" #include "../dsl/node_tags.h" namespace voy { using voy::utils::non_copyable; using voy::dsl::source_node_tag; using voy::dsl::continuator_base; // `values` creates a reactive stream that emits the predefined // values as soon as the pipeline is initialized template class values: non_copyable { voy_assert_value_type(T); public: using node_category = source_node_tag; explicit values(std::initializer_list values) : m_values{values} { } template explicit values(C&& values) : m_values{voy_fwd(values)} { } template class node: public continuator_base, non_copyable { using base = continuator_base; public: node(std::vector&& values, Cont&& cont) - : continuator_base{std::move(cont)} + : base{std::move(cont)} , m_values{std::move(values)} { } void init() { base::init(); for (auto&& value: m_values) { base::emit(std::move(value)); } m_values.clear(); base::notify_ended(); } private: std::vector m_values; }; template auto with_continuation(Cont&& cont) && { return node(std::move(m_values), voy_fwd(cont)); } private: std::vector m_values; }; } // namespace voy #endif // include guard diff --git a/src/voy/main.cpp b/src/voy/main.cpp index 3d02eae..bb2dd1a 100644 --- a/src/voy/main.cpp +++ b/src/voy/main.cpp @@ -1,58 +1,73 @@ /* * Copyright (C) 2018 Ivan Čukić * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. * If not, see . */ #include +#include "basic/delayed.h" +#include "wrappers/process.h" + #include "engine/event_loop.h" #include "basic/values.h" #include "basic/sink.h" -#include "wrappers/process.h" #include "dsl.h" int main(int argc, char *argv[]) { auto cout = [] (auto&& value) { std::cout << "Out: " << voy_fwd(value) << std::endl; }; using voy::dsl::operator|; using namespace std::literals::string_literals; + using namespace std::literals::chrono_literals; // #define VALUES_TEST #ifdef VALUES_TEST - auto pipeline = + auto pipeline_values = voy::values{42, 6} | voy::sink{cout}; #endif -#define PROCESS_TEST +// #define PROCESS_TEST #ifdef PROCESS_TEST - auto pipeline = + auto pipeline_process = voy::system_cmd("task"s) | voy::sink{cout}; #endif +#define DELAYED_TEST +#ifdef DELAYED_TEST + auto pipeline_delayed = + voy::delayed(5s, "I'm finally here"s) | voy::sink{cout}; +#endif + +#define DELAYED_VALS_TEST +#ifdef DELAYED_VALS_TEST + auto pipeline_delayed_values = + voy::delayed_values(2s, {"I'm running late"s, "sorry..."s}) | voy::sink{cout}; +#endif + voy::event_loop::run(); return 0; } diff --git a/src/voy/wrappers/process.h b/src/voy/wrappers/process.h index f006dbd..98c11d5 100644 --- a/src/voy/wrappers/process.h +++ b/src/voy/wrappers/process.h @@ -1,146 +1,144 @@ /* * Copyright (C) 2018 Ivan Čukić * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. * If not, see . */ #ifndef VOY_WRAPPERS_PROCESS_H #define VOY_WRAPPERS_PROCESS_H // STL #include #include // Self #include "../utils.h" #include "../traits.h" #include "../dsl/node_tags.h" #include "../engine/asio/process.h" namespace voy { using voy::utils::non_copyable; -using namespace voy::dsl; - template class process_impl: public non_copyable { public: - using node_category = source_node_tag; + using node_category = dsl::source_node_tag; explicit process_impl(std::tuple command, ValueHandler handler = voy::utils::identity{}) : m_command{std::move(command)} , m_handler(handler) { } template class node: non_copyable { voy_assert_value_type(Cont); template struct composition { voy_assert_value_type(F); voy_assert_value_type(G); F f; G g; composition(F f, G g) : f(std::move(f)) , g(std::move(g)) { } template decltype(auto) operator() (T&& value) const { #define EVAL_F_G std::invoke(f, voy_fwd_invoke(g, value)) if constexpr (std::is_same_v) { EVAL_F_G; } else { return EVAL_F_G; } #undef EVAL_F_G } void init() { f.init(); } void notify_ended() const { f.notify_ended(); } }; public: using value_type = decltype(std::declval()(std::string())); node(Cont&& cont, ValueHandler&& handler, std::tuple command) : m_process( std::make_unique>>( composition(std::move(cont), std::move(handler)), std::move(command) ) ) { } void init() { m_process->init_handler(); } private: std::unique_ptr< voy::engine::asio::process>> m_process; }; template auto with_continuation(Cont&& cont) && { return node( voy_fwd(cont), std::move(m_handler), std::move(m_command)); } private: std::tuple m_command; ValueHandler m_handler; }; template auto process(Cmd&& cmd, Args&&... args) { return process_impl( std::make_tuple(voy_fwd(cmd), voy_fwd(args)...), voy::utils::identity{}); } template auto system_cmd(Cmd&& cmd, Args&&... args) { return process(boost::process::search_path(voy_fwd(cmd)), voy_fwd(args)...); } } #endif // include guard