#ifndef _ASYNCO_ #define _ASYNCO_ #include #include #include #include #include #include #include using namespace std; #include #if __cplusplus >= 202002L #include #include #include #endif using namespace boost::asio; #include "timers.hpp" #include "trigger.hpp" namespace marcelb { namespace asynco { /** * Asynco runtime */ class Asynco { vector _runners; unique_ptr _work; void init_loops_in_threads(uint8_t threads); public: io_context io_ctx; void run(uint8_t threads = thread::hardware_concurrency()); void run_on_this(); void join(); /** * Run the function asynchronously */ template auto async(F&& f, Args&&... args) -> future> { using return_type = invoke_result_t; future res = io_ctx.post(boost::asio::use_future(bind(forward(f), forward(args)...))); return res; } #if __cplusplus >= 202002L /** * Run the coroutine */ template future async(boost::asio::awaitable _coroutine) { promise promise; auto future = promise.get_future(); co_spawn(io_ctx, [_coroutine = move(_coroutine), promise = move(promise)]() mutable -> boost::asio::awaitable { try { if constexpr (!is_void_v) { T result = co_await move(_coroutine); promise.set_value(move(result)); } else { co_await move(_coroutine); promise.set_value(); // Za void ne postavljamo rezultat } } catch (...) { promise.set_exception(current_exception()); // Postavljamo izuzetak } }, boost::asio::detached); return future; } #endif /** * Block until the asynchronous call completes - dont block asynco engine loop */ template T await(future& r, uint16_t time_us = 10) { while (r.wait_for(std::chrono::microseconds(time_us)) != future_status::ready) { io_ctx.poll_one(); } return r.get(); } /** * Block until the asynchronous call completes - dont block asynco engine loop */ template T await(future&& r, uint16_t time_us = 10) { while (r.wait_for(std::chrono::microseconds(time_us)) != future_status::ready) { io_ctx.poll_one(); } return move(r).get(); } /** * Run the function asynchronously an block until completes */ template auto await(F&& f, Args&&... args) -> invoke_result_t { return await( async(f, args...) ); } #if __cplusplus >= 202002L /** * Run the coruotine and wait */ template T await(boost::asio::awaitable _coroutine) { return await( async( move(_coroutine) )); } #endif /** * Block until the multiple asynchronous call completes * Use only on no-void calls */ template auto await(F&&... f) -> tuple::type...> { return make_tuple(move(f).get()...); } /** * Block until the multiple asynchronous call completes * Use only on no-void calls */ template auto await(F&... f) -> tuple::type...> { return make_tuple(await(f)...); } Timer delayed(function callback, uint64_t time) ;/*{ return Timer(io_ctx, callback, time, TimerType::Delayed); }*/ Timer periodic(function callback, uint64_t time) ;/*{ return Timer(io_ctx, callback, time, TimerType::Periodic); }*/ template Trigger trigger() { return Trigger(*this); } }; } } #endif