Skip to content

Commit db6d8cb

Browse files
committed
feat: Change CoroutineTraits::Rebind to CoroutineTraits::ReturnType in register_coroutine_rpc_handler and add documentation
1 parent 79fe6c4 commit db6d8cb

File tree

8 files changed

+35
-17
lines changed

8 files changed

+35
-17
lines changed

doc/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Feature overview, installation and performance benchmark can be found on [github
88
* Main workhorses of this library: `agrpc::GrpcContext`, `agrpc::GrpcExecutor`.
99
* Asynchronous gRPC clients: [cheat sheet](md_doc_2client__rpc__cheat__sheet.html), `agrpc::ClientRPC`,
1010
* Asynchronous gRPC servers: [cheat sheet](md_doc_2server__rpc__cheat__sheet.html), `agrpc::ServerRPC`, `agrpc::register_awaitable_rpc_handler`,
11-
`agrpc::register_yield_rpc_handler`, `agrpc::register_sender_rpc_handler`, `agrpc::register_callback_rpc_handler`
11+
`agrpc::register_yield_rpc_handler`, `agrpc::register_sender_rpc_handler`, `agrpc::register_callback_rpc_handler`, `agrpc::register_coroutine_rpc_handler`
1212
* GRPC Timer: `agrpc::Alarm`
1313
* Combining GrpcContext and `asio::io_context`: `agrpc::run`, `agrpc::run_completion_queue`
1414
* Faster, drop-in replacement for gRPC's [DefaultHealthCheckService](https://github.com/grpc/grpc/blob/v1.50.1/src/cpp/server/health/default_health_check_service.h): `agrpc::HealthCheckService`

example/helper/coro_traits.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121

2222
namespace example
2323
{
24-
template <class Executor = boost::asio::any_io_executor>
24+
/* [asio-coro-traits] */
25+
template <class Executor = boost::asio::any_io_executor, class Allocator = std::allocator<void>>
2526
struct AsioCoroTraits
2627
{
27-
template <class U>
28-
using Rebind = boost::asio::experimental::coro<void, U, Executor>;
28+
using ReturnType = boost::asio::experimental::coro<void, void, Executor, Allocator>;
2929

3030
template <class RPCHandler, class CompletionHandler>
3131
static boost::asio::deferred_t completion_token(RPCHandler&, CompletionHandler&)
@@ -42,6 +42,7 @@ struct AsioCoroTraits
4242
boost::asio::detached);
4343
}
4444
};
45+
/* [asio-coro-traits] */
4546
} // namespace example
4647

4748
#endif // AGRPC_HELPER_CORO_TRAITS_HPP

src/agrpc/detail/coroutine_traits.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@ struct CoroutineTraits;
3535
template <class T, class Executor>
3636
struct CoroutineTraits<asio::awaitable<T, Executor>>
3737
{
38-
template <class U>
39-
using Rebind = asio::awaitable<U, Executor>;
38+
using ReturnType = asio::awaitable<void, Executor>;
4039

4140
template <class RPCHandler, class CompletionHandler>
4241
static asio::use_awaitable_t<Executor> completion_token(RPCHandler&, CompletionHandler&)

src/agrpc/detail/register_coroutine_rpc_handler.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,12 @@ struct RegisterCoroutineRPCHandlerOperation
3636
struct Type : detail::RegisterRPCHandlerOperationAsioBase<ServerRPC, RPCHandler, CompletionHandler>
3737
{
3838
using Base = detail::RegisterRPCHandlerOperationAsioBase<ServerRPC, RPCHandler, CompletionHandler>;
39+
using Awaitable = typename CoroTraits::ReturnType;
3940
using typename Base::Allocator;
4041
using typename Base::RefCountGuard;
4142
using typename Base::ServerRPCExecutor;
4243
using typename Base::Service;
4344

44-
using Awaitable = typename CoroTraits::template Rebind<void>;
45-
4645
template <class Ch>
4746
Type(const ServerRPCExecutor& executor, Service& service, RPCHandler&& rpc_handler, Ch&& completion_handler)
4847
: Base(executor, service, static_cast<RPCHandler&&>(rpc_handler), static_cast<Ch&&>(completion_handler),

src/agrpc/register_awaitable_rpc_handler.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ AGRPC_NAMESPACE_BEGIN()
3434
* first argument and `ServerRPC::Request&` as second argument (only for unary and server-streaming rpcs). The ServerRPC
3535
* is automatically cancelled at the end of the rpc handler if `finish()` was not called earlier. The return value of
3636
* the rpc handler is `co_spawn`ed in a manner similar to:
37-
* `asio::co_spawn(asio::get_associated_executor(completion_handler, executor), rpc_handler())`, where
37+
* `asio::co_spawn(asio::get_associated_executor(completion_handler, executor), rpc_handler)`, where
3838
* `completion_handler` is created from `token` and `executor` the first argument passed to this function.
3939
*
4040
* This asynchronous operation runs forever unless it is cancelled, the rpc handler throws an exception or the server is

src/agrpc/register_coroutine_rpc_handler.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,29 @@ AGRPC_NAMESPACE_BEGIN()
2929
/**
3030
* @brief (experimental) Register a coroutine rpc handler for the given method
3131
*
32+
* The rpc handler will be invoked for every incoming request of this gRPC method. It must take `ServerRPC&` as
33+
* first argument and `ServerRPC::Request&` as second argument (only for unary and server-streaming rpcs). The ServerRPC
34+
* is automatically cancelled at the end of the rpc handler if `finish()` was not called earlier. The return value of
35+
* the rpc handler is `co_spawn`ed in a manner similar to:
36+
* `CoroutineTraits::co_spawn(executor, rpc_handler, completion_handler, function)`, where
37+
* `completion_handler` is created from `token`, `executor` the first argument passed to this function and `function`,
38+
* when invoked, starts waiting for the next rpc. Any arguments passed to `function` will be prepended to the call of
39+
* the rpc handler. The return type of `function` is `CoroutineTraits::ReturnType`, which must be a coroutine, and
40+
* `CoroutineTraits::completion_token` must produce an Asio compatible [completion
41+
* token](https://www.boost.org/doc/libs/1_86_0/doc/html/boost_asio/reference/asynchronous_operations.html#boost_asio.reference.asynchronous_operations.completion_tokens_and_handlers)
42+
* that, when used to initiate an asynchronous operation, returns an awaitable.
43+
*
44+
* This asynchronous operation runs forever unless it is cancelled, the rpc handler throws an exception or the server is
45+
* shutdown
46+
* ([grpc::Server::Shutdown](https://grpc.github.io/grpc/cpp/classgrpc_1_1_server_interface.html#a6a1d337270116c95f387e0abf01f6c6c)
47+
* is called). At which point it invokes the completion handler (passing forward the exception thrown by the request
48+
* handler, if any) after all coroutines produced by invoking the rpc handler complete.
49+
*
3250
* @tparam ServerRPC An instantiation of `agrpc::ServerRPC`
51+
* @tparam CoroutineTraits A class that provides functions for spawning the coroutine of each rpc. Example:
52+
*
53+
* @snippet coro_traits.hpp asio-coro-traits
54+
*
3355
* @param executor The executor used to handle each rpc
3456
* @param service The service associated with the gRPC method of the ServerRPC
3557
* @param rpc_handler A callable that produces a coroutine. The coroutine's return value is ignored.

test/src/test_server_rpc_20.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -558,11 +558,10 @@ TEST_CASE_FIXTURE(ServerRPCAwaitableTest<test::ServerStreamingServerRPC>,
558558
#endif
559559

560560
#ifdef AGRPC_TEST_ASIO_HAS_CORO
561-
template <class Yield, class Return, class Executor>
561+
template <class Executor>
562562
struct CoroTraits
563563
{
564-
template <class U>
565-
using Rebind = asio::experimental::coro<Yield, U, Executor>;
564+
using ReturnType = asio::experimental::coro<void, void, Executor>;
566565

567566
template <class RPCHandler, class CompletionHandler>
568567
static asio::deferred_t completion_token(RPCHandler&, CompletionHandler&)
@@ -608,7 +607,7 @@ TEST_CASE_FIXTURE(ServerRPCAwaitableTest<test::ClientStreamingServerRPC>,
608607
}
609608
};
610609
asio::io_context io_context{1};
611-
agrpc::register_coroutine_rpc_handler<ServerRPC, CoroTraits<void, void, Exec>>(
610+
agrpc::register_coroutine_rpc_handler<ServerRPC, CoroTraits<Exec>>(
612611
get_executor(), service, Handler{}, asio::bind_executor(io_context.get_executor(), test::RethrowFirstArg{}));
613612
std::thread t{[&]
614613
{
@@ -633,8 +632,7 @@ TEST_CASE_FIXTURE(ServerRPCAwaitableTest<test::ClientStreamingServerRPC>,
633632
#ifdef AGRPC_TEST_HAS_BOOST_COBALT
634633
struct BoostCobaltTraits
635634
{
636-
template <class U>
637-
using Rebind = boost::cobalt::task<U>;
635+
using ReturnType = boost::cobalt::task<void>;
638636

639637
template <class RPCHandler, class CompletionHandler>
640638
static boost::cobalt::use_op_t completion_token(RPCHandler&, CompletionHandler&)

test/src/test_unifex_20.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,7 @@ TEST_CASE_FIXTURE(test::ExecutionGrpcContextTest, "unifex Waiter: initiate alarm
247247
#if defined(AGRPC_TEST_ASIO_HAS_CORO) && !UNIFEX_NO_COROUTINES
248248
struct UnifexCoroutineTraits
249249
{
250-
template <class U>
251-
using Rebind = unifex::task<U>;
250+
using ReturnType = unifex::task<void>;
252251

253252
template <class RPCHandler, class CompletionHandler>
254253
static auto completion_token(RPCHandler&, CompletionHandler&)

0 commit comments

Comments
 (0)