asynco/lib/asynco.hpp

123 lines
2.8 KiB
C++

#ifndef _ASYNCO_
#define _ASYNCO_
#include "engine.hpp"
#include <iostream>
using namespace std;
#if __cplusplus >= 202002L
#include <boost/asio/awaitable.hpp>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/use_awaitable.hpp>
#endif
namespace marcelb {
namespace asynco {
/**
* Run the function asynchronously
*/
template<class F, class... Args>
auto async_(F&& f, Args&&... args) -> future<typename result_of<F(Args...)>::type> {
using return_type = typename result_of<F(Args...)>::type;
future<return_type> res = _asynco_engine.io_context.post(boost::asio::use_future(bind(forward<F>(f), forward<Args>(args)...)));
return res;
}
#if __cplusplus >= 202002L
/**
* Run the coroutine
*/
template <typename T>
std::future<T> async_(boost::asio::awaitable<T> _coroutine) {
std::promise<T> promise;
auto future = promise.get_future();
co_spawn(_asynco_engine.io_context, [_coroutine = std::move(_coroutine), promise = std::move(promise)]() mutable -> boost::asio::awaitable<void> {
try {
if constexpr (!std::is_void_v<T>) {
T result = co_await std::move(_coroutine);
promise.set_value(std::move(result));
} else {
co_await std::move(_coroutine);
promise.set_value(); // Za void ne postavljamo rezultat
}
} catch (...) {
promise.set_exception(std::current_exception()); // Postavljamo izuzetak
}
}, boost::asio::detached);
return future;
}
#endif
/**
* Block until the asynchronous call completes
*/
template<typename T>
T await_(future<T>& r) {
return r.get();
}
/**
* Block until the asynchronous call completes
*/
template<typename T>
T await_(future<T>&& r) {
return move(r).get();
}
/**
* Run the function asynchronously an block until completes
*/
template<class F, class... Args>
auto await_(F&& f, Args&&... args) -> typename result_of<F(Args...)>::type {
return await_(
async_(f, args...)
);
}
#if __cplusplus >= 202002L
/**
* Run the coruotine and wait
*/
template <typename T>
T await_(boost::asio::awaitable<T> _coroutine) {
return await_(
async_(
move(_coroutine)
));
}
#endif
/**
* Block until the asynchronous call completes or time expired
*/
// template<typename T>
// T await_(future<T>& r, uint64_t time) {
// if (r.wait_for(chrono::milliseconds(time)) == std::future_status::timeout) {
// throw runtime_error("Asynchronous execution timed out");
// }
// return r.get();
// }
/**
* Block until the asynchronous call completes or time expired
*/
// template<typename T>
// T await_(future<T>&& r, uint64_t time) {
// if (r.wait_for(chrono::milliseconds(time)) == std::future_status::timeout) {
// throw runtime_error("Asynchronous execution timed out");
// }
// return move(r).get();
// }
}
}
#endif