Skip to content

Commit

Permalink
lazy callback (#539)
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos authored Mar 22, 2024
1 parent 1d44c39 commit d6f60e0
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 17 deletions.
15 changes: 1 addition & 14 deletions include/cinatra/coro_http_router.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
#pragma once
#include <async_simple/coro/Lazy.h>

#include <algorithm>
#include <functional>
#include <set>
Expand All @@ -17,17 +15,6 @@
#include "ylt/util/type_traits.h"

namespace cinatra {
template <template <typename...> class U, typename T>
struct is_template_instant_of : std::false_type {};

template <template <typename...> class U, typename... args>
struct is_template_instant_of<U, U<args...>> : std::true_type {};

template <typename T>
constexpr inline bool is_lazy_v =
is_template_instant_of<async_simple::coro::Lazy,
std::remove_cvref_t<T>>::value;

template <class, class = void>
struct has_before : std::false_type {};

Expand Down Expand Up @@ -64,7 +51,7 @@ class coro_http_router {
// hold keys to make sure map_handles_ key is
// std::string_view, avoid memcpy when route
using return_type = typename util::function_traits<Func>::return_type;
if constexpr (is_lazy_v<return_type>) {
if constexpr (coro_io::is_lazy_v<return_type>) {
std::function<async_simple::coro::Lazy<void>(coro_http_request & req,
coro_http_response & resp)>
http_handler;
Expand Down
2 changes: 1 addition & 1 deletion include/cinatra/coro_http_server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ class coro_http_server {
static_assert(std::is_member_function_pointer_v<Func>,
"must be member function");
using return_type = typename util::function_traits<Func>::return_type;
if constexpr (is_lazy_v<return_type>) {
if constexpr (coro_io::is_lazy_v<return_type>) {
std::function<async_simple::coro::Lazy<void>(coro_http_request & req,
coro_http_response & resp)>
f = std::bind(handler, &owner, std::placeholders::_1,
Expand Down
64 changes: 62 additions & 2 deletions include/cinatra/ylt/coro_io/coro_io.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include <asio/ssl.hpp>
#endif

#include <async_simple/coro/Lazy.h>

#include <asio/connect.hpp>
#include <asio/dispatch.hpp>
#include <asio/experimental/channel.hpp>
Expand All @@ -26,6 +28,9 @@
#include "io_context_pool.hpp"

namespace coro_io {
template <typename T>
constexpr inline bool is_lazy_v =
util::is_specialization_v<std::remove_cvref_t<T>, async_simple::coro::Lazy>;

template <typename Arg, typename Derived>
class callback_awaitor_base {
Expand Down Expand Up @@ -380,9 +385,64 @@ async_simple::coro::Lazy<std::pair<
});
}

template <typename T>
inline decltype(auto) select_impl(T &pair) {
using Func = std::tuple_element_t<1, std::remove_cvref_t<T>>;
using ValueType =
typename std::tuple_element_t<0, std::remove_cvref_t<T>>::ValueType;
using return_type = std::invoke_result_t<Func, async_simple::Try<ValueType>>;

auto &callback = std::get<1>(pair);
if constexpr (coro_io::is_lazy_v<return_type>) {
auto executor = std::get<0>(pair).getExecutor();
return std::make_pair(
std::move(std::get<0>(pair)),
[executor, callback = std::move(callback)](auto &&val) {
if (executor) {
callback(std::move(val)).via(executor).start([](auto &&) {
});
}
else {
callback(std::move(val)).start([](auto &&) {
});
}
});
}
else {
return pair;
}
}

template <typename... T>
auto select(T &&...args) {
return async_simple::coro::collectAny(std::forward<T>(args)...);
inline auto select(T &&...args) {
return async_simple::coro::collectAny(select_impl(args)...);
}

template <typename T, typename Callback>
inline auto select(std::vector<T> vec, Callback callback) {
if constexpr (coro_io::is_lazy_v<Callback>) {
std::vector<async_simple::Executor *> executors;
for (auto &lazy : vec) {
executors.push_back(lazy.getExecutor());
}

return async_simple::coro::collectAny(
std::move(vec),
[executors, callback = std::move(callback)](size_t index, auto &&val) {
auto executor = executors[index];
if (executor) {
callback(index, std::move(val)).via(executor).start([](auto &&) {
});
}
else {
callback(index, std::move(val)).start([](auto &&) {
});
}
});
}
else {
return async_simple::coro::collectAny(std::move(vec), std::move(callback));
}
}

template <typename Socket, typename AsioBuffer>
Expand Down

0 comments on commit d6f60e0

Please sign in to comment.