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"
24# pragma warning(disable : 4250)
25# pragma warning(disable : 4251)
26#elif defined(__clang__)
27# pragma clang diagnostic push
29# pragma clang diagnostic ignored "-Wshadow-uncaptured-local"
30# pragma clang diagnostic ignored "-Wweak-vtables"
35 class OutgoingAsyncBase;
37 class CollocatedRequestHandler;
41 AsyncStatusQueued = 0,
43 AsyncStatusInvokeSentCallback = 2
46 class ICE_API OutgoingAsyncCompletionCallback
49 virtual ~OutgoingAsyncCompletionCallback();
53 virtual bool handleSent(
bool done,
bool alreadySent)
noexcept = 0;
56 virtual bool handleException(std::exception_ptr)
noexcept = 0;
60 virtual bool handleResponse(
bool) = 0;
62 virtual void handleInvokeSent(
bool, OutgoingAsyncBase*)
const = 0;
63 virtual void handleInvokeException(std::exception_ptr, OutgoingAsyncBase*)
const = 0;
64 virtual void handleInvokeResponse(
bool, OutgoingAsyncBase*)
const = 0;
72 class ICE_API OutgoingAsyncBase :
public virtual OutgoingAsyncCompletionCallback,
73 public std::enable_shared_from_this<OutgoingAsyncBase>
77 virtual bool exception(std::exception_ptr);
78 virtual bool response();
80 void invokeSentAsync();
81 void invokeExceptionAsync();
82 void invokeResponseAsync();
85 void invokeException();
86 void invokeResponse();
88 virtual void cancelable(
const IceInternal::CancellationHandlerPtr&);
96 Ice::OutputStream* getOs() {
return &_os; }
98 Ice::InputStream* getIs() {
return &_is; }
101 OutgoingAsyncBase(
const InstancePtr&);
104 bool exceptionImpl(std::exception_ptr);
105 bool responseImpl(
bool,
bool);
107 void cancel(std::exception_ptr);
109 void warning(std::string_view callbackName, std::exception_ptr eptr)
const;
115 virtual IceInternal::InvocationObserver& getObserver() {
return _observer; }
117 const InstancePtr _instance;
119 bool _sentSynchronously{
false};
120 bool _doneInSent{
false};
121 unsigned char _state{0};
124 using Lock = std::lock_guard<std::mutex>;
126 std::exception_ptr _ex;
127 std::exception_ptr _cancellationException;
129 InvocationObserver _observer;
130 ObserverHelperT<Ice::Instrumentation::ChildInvocationObserver> _childObserver;
132 Ice::OutputStream _os;
133 Ice::InputStream _is;
135 CancellationHandlerPtr _cancellationHandler;
137 static const unsigned char OK;
138 static const unsigned char Sent;
141 using OutgoingAsyncBasePtr = std::shared_ptr<OutgoingAsyncBase>;
149 class ICE_API ProxyOutgoingAsyncBase :
public OutgoingAsyncBase,
public TimerTask
152 virtual AsyncStatus invokeRemote(
const Ice::ConnectionIPtr&,
bool,
bool) = 0;
153 virtual AsyncStatus invokeCollocated(CollocatedRequestHandler*) = 0;
155 bool exception(std::exception_ptr)
override;
157 void retryException();
159 void abort(std::exception_ptr);
161 std::shared_ptr<ProxyOutgoingAsyncBase> shared_from_this()
163 return std::static_pointer_cast<ProxyOutgoingAsyncBase>(OutgoingAsyncBase::shared_from_this());
167 ProxyOutgoingAsyncBase(Ice::ObjectPrx);
168 ~ProxyOutgoingAsyncBase()
override;
170 void invokeImpl(
bool);
172 bool exceptionImpl(std::exception_ptr);
173 bool responseImpl(
bool,
bool);
175 void runTimerTask()
override;
177 const Ice::ObjectPrx _proxy;
178 RequestHandlerPtr _handler;
182 int handleRetryAfterException(std::exception_ptr);
183 int checkRetryAfterException(std::exception_ptr);
189 using ProxyOutgoingAsyncBasePtr = std::shared_ptr<ProxyOutgoingAsyncBase>;
194 class ICE_API OutgoingAsync :
public ProxyOutgoingAsyncBase
197 OutgoingAsync(Ice::ObjectPrx,
bool);
201 bool sent()
override;
202 bool response()
override;
204 AsyncStatus invokeRemote(
const Ice::ConnectionIPtr&,
bool,
bool)
override;
205 AsyncStatus invokeCollocated(CollocatedRequestHandler*)
override;
207 void abort(std::exception_ptr);
208 void invoke(std::string_view);
212 std::optional<Ice::FormatType>,
214 const std::function<
void(Ice::OutputStream*)>&);
215 void throwUserException();
217 Ice::OutputStream* startWriteParams(std::optional<Ice::FormatType> format)
219 _os.startEncapsulation(_encoding, format);
222 void endWriteParams() { _os.endEncapsulation(); }
223 void writeEmptyParams() { _os.writeEmptyEncapsulation(_encoding); }
224 void writeParamEncaps(
const std::byte* encaps, std::int32_t size)
228 _os.writeEmptyEncapsulation(_encoding);
232 _os.writeEncapsulation(encaps, size);
237 const Ice::EncodingVersion _encoding;
242 using OutgoingAsyncPtr = std::shared_ptr<OutgoingAsync>;
244 class ICE_API LambdaInvoke :
public virtual OutgoingAsyncCompletionCallback
247 LambdaInvoke(std::function<
void(std::exception_ptr)> exception, std::function<
void(
bool)> sent)
248 : _exception(std::move(exception)),
249 _sent(std::move(sent))
254 bool handleSent(
bool,
bool)
noexcept final;
255 bool handleException(std::exception_ptr)
noexcept final;
256 bool handleResponse(
bool)
final;
258 void handleInvokeSent(
bool, OutgoingAsyncBase*)
const final;
259 void handleInvokeException(std::exception_ptr, OutgoingAsyncBase*)
const final;
260 void handleInvokeResponse(
bool, OutgoingAsyncBase*)
const final;
262 std::function<void(std::exception_ptr)> _exception;
263 std::function<void(
bool)> _sent;
264 std::function<void(
bool)> _response;
267 template<
typename R>
class PromiseInvoke :
public virtual OutgoingAsyncCompletionCallback
270 [[nodiscard]] std::future<R> getFuture() {
return _promise.get_future(); }
273 bool handleSent(
bool,
bool)
noexcept override {
return false; }
275 bool handleException(std::exception_ptr ex)
noexcept final
277 _promise.set_exception(ex);
281 bool handleResponse(
bool ok)
final
287 void handleInvokeSent(
bool, OutgoingAsyncBase*)
const final { assert(
false); }
289 void handleInvokeException(std::exception_ptr, OutgoingAsyncBase*)
const final { assert(
false); }
291 void handleInvokeResponse(
bool, OutgoingAsyncBase*)
const final { assert(
false); }
293 std::promise<R> _promise;
294 std::function<void(
bool)> _response;
297 template<
typename T>
class OutgoingAsyncT :
public OutgoingAsync
300 using OutgoingAsync::OutgoingAsync;
303 std::string_view operation,
305 std::optional<Ice::FormatType> format,
307 const std::function<
void(Ice::OutputStream*)>& write,
310 _read = [](Ice::InputStream* stream)
316 _userException = std::move(userException);
317 OutgoingAsync::invoke(operation, mode, format, ctx, write);
321 std::string_view operation,
323 std::optional<Ice::FormatType> format,
325 const std::function<
void(Ice::OutputStream*)>& write,
327 std::function<T(Ice::InputStream*)> read)
329 _read = std::move(read);
330 _userException = std::move(userException);
331 OutgoingAsync::invoke(operation, mode, format, ctx, write);
335 std::function<T(Ice::InputStream*)> _read;
338 template<>
class OutgoingAsyncT<void> :
public OutgoingAsync
341 using OutgoingAsync::OutgoingAsync;
344 std::string_view operation,
346 std::optional<Ice::FormatType> format,
348 const std::function<
void(Ice::OutputStream*)>& write,
351 _userException = std::move(userException);
352 OutgoingAsync::invoke(operation, mode, format, ctx, write);
356 template<
typename R>
class LambdaOutgoing :
public OutgoingAsyncT<R>,
public LambdaInvoke
360 Ice::ObjectPrx proxy,
361 std::function<
void(R)> response,
362 std::function<
void(std::exception_ptr)> ex,
363 std::function<
void(
bool)> sent)
364 : OutgoingAsyncT<R>(std::move(proxy), false),
365 LambdaInvoke(std::move(ex), std::move(sent))
367 _response = [
this, response = std::move(response)](
bool ok)
371 this->throwUserException();
376 this->_is.startEncapsulation();
377 R v = this->_read(&this->_is);
378 this->_is.endEncapsulation();
381 response(std::move(v));
385 this->warning(
"response", std::current_exception());
392 template<>
class LambdaOutgoing<void> :
public OutgoingAsyncT<void>,
public LambdaInvoke
396 Ice::ObjectPrx proxy,
397 std::function<
void()> response,
398 std::function<
void(std::exception_ptr)> ex,
399 std::function<
void(
bool)> sent)
400 : OutgoingAsyncT<void>(std::move(proxy), false),
401 LambdaInvoke(std::move(ex), std::move(sent))
403 _response = [
this, response = std::move(response)](
bool ok)
407 this->throwUserException();
411 if (!this->_is.b.empty())
413 this->_is.skipEmptyEncapsulation();
421 this->warning(
"response", std::current_exception());
428 template<
typename R>
class PromiseOutgoing :
public OutgoingAsyncT<R>,
public PromiseInvoke<R>
431 PromiseOutgoing(Ice::ObjectPrx proxy,
bool sync) : OutgoingAsyncT<R>(std::move(proxy), sync)
433 this->_response = [
this](
bool ok)
438 this->_is.startEncapsulation();
439 R v = this->_read(&this->_is);
440 this->_is.endEncapsulation();
441 this->_promise.set_value(std::move(v));
445 this->throwUserException();
451 template<>
class PromiseOutgoing<void> :
public OutgoingAsyncT<void>,
public PromiseInvoke<void>
454 PromiseOutgoing(Ice::ObjectPrx proxy,
bool sync) : OutgoingAsyncT<void>(std::move(proxy), sync)
456 this->_response = [&](
bool ok)
458 if (this->_is.b.empty())
465 this->_promise.set_value();
469 this->_is.skipEmptyEncapsulation();
470 this->_promise.set_value();
474 this->throwUserException();
479 bool handleSent(
bool done,
bool)
noexcept final
483 PromiseInvoke<void>::_promise.set_value();
489 template<
typename R,
typename Obj,
typename Fn,
typename... Args>
490 [[nodiscard]]
inline std::future<R> makePromiseOutgoing(
bool sync, Obj obj, Fn fn, Args&&... args)
492 auto outAsync = std::make_shared<PromiseOutgoing<R>>(*obj, sync);
493 (obj->*fn)(outAsync, std::forward<Args>(args)...);
494 return outAsync->getFuture();
497 template<
typename R,
typename Re,
typename E,
typename S,
typename Obj,
typename Fn,
typename... Args>
498 [[nodiscard]]
inline std::function<void()> makeLambdaOutgoing(Re r, E e, S s, Obj obj, Fn fn, Args&&... args)
500 auto outAsync = std::make_shared<LambdaOutgoing<R>>(*obj, std::move(r), std::move(e), std::move(s));
501 (obj->*fn)(outAsync, std::forward<Args>(args)...);
502 return [outAsync]() { outAsync->cancel(); };
508#elif defined(__clang__)
509# 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.