21template <
typename Response>
25 template <
typename Context>
31 template <
typename CompletionHandler>
35 static_assert(std::is_invocable_v<CompletionHandler, Response&>);
39 std::decay_t<CompletionHandler> handler;
43 [](
UA_Client*,
void* userdata, uint32_t ,
void* responsePtr) {
44 std::unique_ptr<Context> context{
static_cast<Context*
>(userdata)};
45 assert(context !=
nullptr);
46 assert(context->catcher !=
nullptr);
47 context->catcher->invoke([context = context.get(), responsePtr] {
48 if (responsePtr == nullptr) {
49 throw BadStatus(UA_STATUSCODE_BADUNEXPECTEDERROR);
51 std::invoke(context->handler, *
static_cast<Response*
>(responsePtr));
55 return CallbackAndContext<Context>{
57 std::make_unique<Context>(
58 Context{&exceptionCatcher, std::forward<CompletionHandler>(handler)}
70 template <
typename Initiation,
typename CompletionToken>
71 static auto initiate(
Client& client, Initiation&& initiation, CompletionToken&& token) {
72 static_assert(std::is_invocable_v<Initiation, UA_ClientAsyncServiceCallback, void*>);
79 auto callbackAndContext = createCallbackAndContext(
80 catcher, std::forward<
decltype(handler)>(handler)
83 std::forward<Initiation>(initiation),
84 callbackAndContext.callback,
85 callbackAndContext.context.get()
89 callbackAndContext.context.release();
91 catcher.setException(std::current_exception());
94 std::forward<CompletionToken>(token)
100template <
typename Request,
typename Response,
typename CompletionToken>
108 &getDataType<Request>(),
110 &getDataType<Response>(),
115 std::forward<CompletionToken>(token)
120template <
typename Request,
typename Response>
126 &getDataType<Request>(),
128 &getDataType<Response>()
Catch & store exceptions from user-defined callbacks in an exception-unaware context (open62541).
void(* UA_ClientAsyncServiceCallback)(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response)
void __UA_Client_Service(UA_Client *client, const void *request, const UA_DataType *requestType, void *response, const UA_DataType *responseType)
UA_StatusCode __UA_Client_AsyncService(UA_Client *client, const void *request, const UA_DataType *requestType, UA_ClientAsyncServiceCallback callback, const UA_DataType *responseType, void *userdata, UA_UInt32 *requestId)
auto asyncInitiate(Initiation &&initiation, CompletionToken &&token, Args &&... args)
UA_Client * getHandle(Client &client) noexcept
ExceptionCatcher * getExceptionCatcher(UA_Client *client) noexcept
Response sendRequest(Client &client, const Request &request) noexcept
Sync client service requests.
auto sendRequestAsync(Client &client, const Request &request, CompletionToken &&token)
Async client service requests.
constexpr void throwIfBad(UA_StatusCode code)
Check the status code and throw a BadStatus exception if the status code is bad.
UA_ClientAsyncServiceCallback callback
std::unique_ptr< Context > context
Adapter to initiate open62541 async client operations with completion tokens.
static auto createCallbackAndContext(ExceptionCatcher &exceptionCatcher, CompletionHandler &&handler)
static auto initiate(Client &client, Initiation &&initiation, CompletionToken &&token)
Initiate open62541 async client operation with user-defined completion token.