asio-grpc v3.3.0
Asynchronous gRPC with Asio/unified executors
Loading...
Searching...
No Matches
agrpc::Waiter< Signature, Executor > Class Template Reference

(experimental) Utility class for uncancelable operations More...

#include <agrpc/waiter.hpp>

Classes

struct  rebind_executor
 Rebind the Waiter to another executor. More...
 

Public Types

using executor_type = Executor
 The associated executor type.
 

Public Member Functions

 Waiter () noexcept
 Default construct a Waiter.
 
 ~Waiter () noexcept
 Destruct the Waiter.
 
template<class Function , class ExecutorOrIoObject , class... Args>
auto initiate (Function &&function, ExecutorOrIoObject &&executor_or_io_object, Args &&... args)
 Initiate an operation.
 
bool is_ready () const noexcept
 Has the initiated operation finished?
 
template<class CompletionToken = detail::DefaultCompletionTokenT<Executor>>
auto wait (CompletionToken &&token=CompletionToken{})
 Wait for the initiated operation to complete.
 

Detailed Description

template<class Signature, class Executor>
class agrpc::Waiter< Signature, Executor >

(experimental) Utility class for uncancelable operations

Provides cancellation support for otherwise uncancelable operations by canceling only the act of waiting for completion as opposed to the operation itself.

Note, this is a general purpose Asio utility and as such does not belong into asio-grpc. For coroutines, Boost.Cobalt offers a replacement in the form of boost::cobalt::promise with its interrupt wait feature.

Template Parameters
SignatureCompletion signature of the operation. For example, for agrpc::Alarm::wait this would be void(bool).
ExecutorType of the I/O executor. For agrpc::Alarm this would be agrpc::GrpcExecutor or asio::any_io_executor. Default: agrpc::GrpcExecutor
Since
2.7.0 (and Boost.Asio 1.77.0)

Constructor & Destructor Documentation

◆ ~Waiter()

template<class Signature , class Executor >
agrpc::Waiter< Signature, Executor >::~Waiter ( )
inlinenoexcept

Destruct the Waiter.

All initiated operations must have been wait()ed for, otherwise the behavior is undefined.

Member Function Documentation

◆ initiate()

template<class Signature , class Executor >
template<class Function , class ExecutorOrIoObject , class... Args>
auto agrpc::Waiter< Signature, Executor >::initiate ( Function && function,
ExecutorOrIoObject && executor_or_io_object,
Args &&... args )
inline

Initiate an operation.

Only one operation may be running at a time.

All operations must complete before this object is destructed.

Example:

asio::awaitable<void> rpc_handler_using_waiter(ServerRPC& rpc)
{
ServerRPC::Request request;
ServerRPC::Response response;
agrpc::Alarm alarm{rpc.get_executor()};
agrpc::Waiter<void(bool)> waiter;
waiter.initiate(agrpc::read, rpc, request);
auto next_deadline = std::chrono::system_clock::now() + std::chrono::seconds(5);
// Read requests from the client and send a response back every five seconds
while (true)
{
auto [completion_order, read_error_code, read_ok, alarm_expired] =
co_await asio::experimental::make_parallel_group(waiter.wait(asio::deferred),
alarm.wait(next_deadline, asio::deferred))
.async_wait(asio::experimental::wait_for_one(), asio::use_awaitable);
if (0 == completion_order[0]) // read completed
{
if (!read_ok)
{
co_return;
}
waiter.initiate(agrpc::read, rpc, request);
}
else // alarm expired
{
co_await rpc.write(response, asio::use_awaitable);
next_deadline = std::chrono::system_clock::now() + std::chrono::seconds(5);
}
}
}
Attention
When using sender/receiver and function returns a sender then only the set_value channel is forwarded to the waiting operation.
Parameters
functionCallable that will be invoked with all subsequent arguments followed by the completion handler of this Waiter (Asio) or it returns a sender composed of the result of the call (unifex/stdexec only).
executor_or_io_objectEither an executor itself or an object that implements get_executor(). This will become the I/O executor of subsequent calls to wait().

◆ is_ready()

template<class Signature , class Executor >
bool agrpc::Waiter< Signature, Executor >::is_ready ( ) const
inlinenodiscardnoexcept

Has the initiated operation finished?

Thread-safe

◆ wait()

template<class Signature , class Executor >
template<class CompletionToken = detail::DefaultCompletionTokenT<Executor>>
auto agrpc::Waiter< Signature, Executor >::wait ( CompletionToken && token = CompletionToken{})
inline

Wait for the initiated operation to complete.

Only one call to wait() may be outstanding at a time. May be called before an operation has been initiated. Care must be taken when invoking this function multiple times for an already completed operation as completion arguments are moved into the completion handler.

Per-Operation Cancellation

All. Upon cancellation, the initiated operation continues to run.