3#ifndef ICE_OUTGOING_ASYNC_H
4#define ICE_OUTGOING_ASYNC_H
6#include "CommunicatorF.h"
7#include "ConnectionF.h"
8#include "ConnectionIF.h"
9#include "InputStream.h"
10#include "LocalExceptions.h"
11#include "ObjectAdapterF.h"
12#include "ObserverHelper.h"
13#include "OutputStream.h"
15#include "RequestHandlerF.h"
23# pragma clang diagnostic push
25# pragma clang diagnostic ignored "-Wshadow-uncaptured-local"
26# pragma clang diagnostic ignored "-Wweak-vtables"
31 class OutgoingAsyncBase;
33 class CollocatedRequestHandler;
37 AsyncStatusQueued = 0,
39 AsyncStatusInvokeSentCallback = 2
42 class ICE_API OutgoingAsyncCompletionCallback
45 virtual ~OutgoingAsyncCompletionCallback();
49 virtual bool handleSent(
bool done,
bool alreadySent)
noexcept = 0;
52 virtual bool handleException(std::exception_ptr)
noexcept = 0;
56 virtual bool handleResponse(
bool) = 0;
58 virtual void handleInvokeSent(
bool, OutgoingAsyncBase*)
const = 0;
59 virtual void handleInvokeException(std::exception_ptr, OutgoingAsyncBase*)
const = 0;
60 virtual void handleInvokeResponse(
bool, OutgoingAsyncBase*)
const = 0;
68 class ICE_API OutgoingAsyncBase :
public virtual OutgoingAsyncCompletionCallback,
69 public std::enable_shared_from_this<OutgoingAsyncBase>
73 virtual bool exception(std::exception_ptr);
74 virtual bool response();
76 void invokeSentAsync();
77 void invokeExceptionAsync();
78 void invokeResponseAsync();
81 void invokeException();
82 void invokeResponse();
84 virtual void cancelable(
const IceInternal::CancellationHandlerPtr&);
92 Ice::OutputStream* getOs() {
return &_os; }
94 Ice::InputStream* getIs() {
return &_is; }
97 OutgoingAsyncBase(
const InstancePtr&);
100 bool exceptionImpl(std::exception_ptr);
101 bool responseImpl(
bool,
bool);
103 void cancel(std::exception_ptr);
105 void warning(std::string_view callbackName, std::exception_ptr eptr)
const;
111 virtual IceInternal::InvocationObserver& getObserver() {
return _observer; }
113 const InstancePtr _instance;
115 bool _sentSynchronously{
false};
116 bool _doneInSent{
false};
117 unsigned char _state{0};
120 using Lock = std::lock_guard<std::mutex>;
122 std::exception_ptr _ex;
123 std::exception_ptr _cancellationException;
125 InvocationObserver _observer;
126 ObserverHelperT<Ice::Instrumentation::ChildInvocationObserver> _childObserver;
128 Ice::OutputStream _os;
129 Ice::InputStream _is;
131 CancellationHandlerPtr _cancellationHandler;
133 static const unsigned char OK;
134 static const unsigned char Sent;
137 using OutgoingAsyncBasePtr = std::shared_ptr<OutgoingAsyncBase>;
145 class ICE_API ProxyOutgoingAsyncBase :
public OutgoingAsyncBase,
public TimerTask
148 virtual AsyncStatus invokeRemote(
const Ice::ConnectionIPtr&,
bool,
bool) = 0;
149 virtual AsyncStatus invokeCollocated(CollocatedRequestHandler*) = 0;
151 bool exception(std::exception_ptr)
override;
153 void retryException();
155 void abort(std::exception_ptr);
157 std::shared_ptr<ProxyOutgoingAsyncBase> shared_from_this()
159 return std::static_pointer_cast<ProxyOutgoingAsyncBase>(OutgoingAsyncBase::shared_from_this());
163 ProxyOutgoingAsyncBase(Ice::ObjectPrx);
164 ~ProxyOutgoingAsyncBase()
override;
166 void invokeImpl(
bool);
168 bool exceptionImpl(std::exception_ptr);
169 bool responseImpl(
bool,
bool);
171 void runTimerTask()
override;
173 const Ice::ObjectPrx _proxy;
174 RequestHandlerPtr _handler;
178 int handleRetryAfterException(std::exception_ptr);
179 int checkRetryAfterException(std::exception_ptr);
185 using ProxyOutgoingAsyncBasePtr = std::shared_ptr<ProxyOutgoingAsyncBase>;
190 class ICE_API OutgoingAsync :
public ProxyOutgoingAsyncBase
193 OutgoingAsync(Ice::ObjectPrx,
bool);
197 bool sent()
override;
198 bool response()
override;
200 AsyncStatus invokeRemote(
const Ice::ConnectionIPtr&,
bool,
bool)
override;
201 AsyncStatus invokeCollocated(CollocatedRequestHandler*)
override;
203 void abort(std::exception_ptr);
204 void invoke(std::string_view);
208 std::optional<Ice::FormatType>,
210 const std::function<
void(Ice::OutputStream*)>&);
211 void throwUserException();
213 Ice::OutputStream* startWriteParams(std::optional<Ice::FormatType> format)
215 _os.startEncapsulation(_encoding, format);
218 void endWriteParams() { _os.endEncapsulation(); }
219 void writeEmptyParams() { _os.writeEmptyEncapsulation(_encoding); }
220 void writeParamEncaps(
const std::byte* encaps, std::int32_t size)
224 _os.writeEmptyEncapsulation(_encoding);
228 _os.writeEncapsulation(encaps, size);
233 const Ice::EncodingVersion _encoding;
238 using OutgoingAsyncPtr = std::shared_ptr<OutgoingAsync>;
240 class ICE_API LambdaInvoke :
public virtual OutgoingAsyncCompletionCallback
243 LambdaInvoke(std::function<
void(std::exception_ptr)> exception, std::function<
void(
bool)> sent)
244 : _exception(std::move(exception)),
245 _sent(std::move(sent))
250 bool handleSent(
bool,
bool)
noexcept final;
251 bool handleException(std::exception_ptr)
noexcept final;
252 bool handleResponse(
bool)
final;
254 void handleInvokeSent(
bool, OutgoingAsyncBase*)
const final;
255 void handleInvokeException(std::exception_ptr, OutgoingAsyncBase*)
const final;
256 void handleInvokeResponse(
bool, OutgoingAsyncBase*)
const final;
258 std::function<void(std::exception_ptr)> _exception;
259 std::function<void(
bool)> _sent;
260 std::function<void(
bool)> _response;
263 template<
typename R>
class PromiseInvoke :
public virtual OutgoingAsyncCompletionCallback
266 [[nodiscard]] std::future<R> getFuture() {
return _promise.get_future(); }
269 bool handleSent(
bool,
bool)
noexcept override {
return false; }
271 bool handleException(std::exception_ptr ex)
noexcept final
273 _promise.set_exception(ex);
277 bool handleResponse(
bool ok)
final
283 void handleInvokeSent(
bool, OutgoingAsyncBase*)
const final { assert(
false); }
285 void handleInvokeException(std::exception_ptr, OutgoingAsyncBase*)
const final { assert(
false); }
287 void handleInvokeResponse(
bool, OutgoingAsyncBase*)
const final { assert(
false); }
289 std::promise<R> _promise;
290 std::function<void(
bool)> _response;
293 template<
typename T>
class OutgoingAsyncT :
public OutgoingAsync
296 using OutgoingAsync::OutgoingAsync;
299 std::string_view operation,
301 std::optional<Ice::FormatType> format,
303 const std::function<
void(Ice::OutputStream*)>& write,
306 _read = [](Ice::InputStream* stream)
312 _userException = std::move(userException);
313 OutgoingAsync::invoke(operation, mode, format, ctx, write);
317 std::string_view operation,
319 std::optional<Ice::FormatType> format,
321 const std::function<
void(Ice::OutputStream*)>& write,
323 std::function<T(Ice::InputStream*)> read)
325 _read = std::move(read);
326 _userException = std::move(userException);
327 OutgoingAsync::invoke(operation, mode, format, ctx, write);
331 std::function<T(Ice::InputStream*)> _read;
334 template<>
class OutgoingAsyncT<void> :
public OutgoingAsync
337 using OutgoingAsync::OutgoingAsync;
340 std::string_view operation,
342 std::optional<Ice::FormatType> format,
344 const std::function<
void(Ice::OutputStream*)>& write,
347 _userException = std::move(userException);
348 OutgoingAsync::invoke(operation, mode, format, ctx, write);
352 template<
typename R>
class LambdaOutgoing :
public OutgoingAsyncT<R>,
public LambdaInvoke
356 Ice::ObjectPrx proxy,
357 std::function<
void(R)> response,
358 std::function<
void(std::exception_ptr)> ex,
359 std::function<
void(
bool)> sent)
360 : OutgoingAsyncT<R>(std::move(proxy), false),
361 LambdaInvoke(std::move(ex), std::move(sent))
363 _response = [
this, response = std::move(response)](
bool ok)
367 this->throwUserException();
372 this->_is.startEncapsulation();
373 R v = this->_read(&this->_is);
374 this->_is.endEncapsulation();
377 response(std::move(v));
381 this->warning(
"response", std::current_exception());
388 template<>
class LambdaOutgoing<void> :
public OutgoingAsyncT<void>,
public LambdaInvoke
392 Ice::ObjectPrx proxy,
393 std::function<
void()> response,
394 std::function<
void(std::exception_ptr)> ex,
395 std::function<
void(
bool)> sent)
396 : OutgoingAsyncT<void>(std::move(proxy), false),
397 LambdaInvoke(std::move(ex), std::move(sent))
399 _response = [
this, response = std::move(response)](
bool ok)
403 this->throwUserException();
407 if (!this->_is.b.empty())
409 this->_is.skipEmptyEncapsulation();
417 this->warning(
"response", std::current_exception());
424 template<
typename R>
class PromiseOutgoing :
public OutgoingAsyncT<R>,
public PromiseInvoke<R>
427 PromiseOutgoing(Ice::ObjectPrx proxy,
bool sync) : OutgoingAsyncT<R>(std::move(proxy), sync)
429 this->_response = [
this](
bool ok)
434 this->_is.startEncapsulation();
435 R v = this->_read(&this->_is);
436 this->_is.endEncapsulation();
437 this->_promise.set_value(std::move(v));
441 this->throwUserException();
447 template<>
class PromiseOutgoing<void> :
public OutgoingAsyncT<void>,
public PromiseInvoke<void>
450 PromiseOutgoing(Ice::ObjectPrx proxy,
bool sync) : OutgoingAsyncT<void>(std::move(proxy), sync)
452 this->_response = [&](
bool ok)
454 if (this->_is.b.empty())
461 this->_promise.set_value();
465 this->_is.skipEmptyEncapsulation();
466 this->_promise.set_value();
470 this->throwUserException();
475 bool handleSent(
bool done,
bool)
noexcept final
479 PromiseInvoke<void>::_promise.set_value();
485 template<
typename R,
typename Obj,
typename Fn,
typename... Args>
486 [[nodiscard]]
inline std::future<R> makePromiseOutgoing(
bool sync, Obj obj, Fn fn, Args&&... args)
488 auto outAsync = std::make_shared<PromiseOutgoing<R>>(*obj, sync);
489 (obj->*fn)(outAsync, std::forward<Args>(args)...);
490 return outAsync->getFuture();
493 template<
typename R,
typename Re,
typename E,
typename S,
typename Obj,
typename Fn,
typename... Args>
494 [[nodiscard]]
inline std::function<void()> makeLambdaOutgoing(Re r, E e, S s, Obj obj, Fn fn, Args&&... args)
496 auto outAsync = std::make_shared<LambdaOutgoing<R>>(*obj, std::move(r), std::move(e), std::move(s));
497 (obj->*fn)(outAsync, std::forward<Args>(args)...);
498 return [outAsync]() { outAsync->cancel(); };
502#if defined(__clang__)
503# pragma clang diagnostic pop
std::shared_ptr< ConnectionInfo > ConnectionInfoPtr
A shared pointer to a ConnectionInfo.
std::shared_ptr< ObjectAdapter > ObjectAdapterPtr
A shared pointer to an ObjectAdapter.
std::shared_ptr< Endpoint > EndpointPtr
A shared pointer to an Endpoint.
OperationMode
Specifies if an operation is idempotent, which affects the retry behavior of the Ice client runtime.
@ Normal
A non-idempotent operation (the default).
std::shared_ptr< Connection > ConnectionPtr
A shared pointer to a Connection.
@ UserException
The dispatch completed with a Slice user exception.
std::map< std::string, std::string, std::less<> > Context
Represents additional information carried by an Ice request.