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
28# pragma clang diagnostic ignored "-Wshadow-uncaptured-local"
29# pragma clang diagnostic ignored "-Wweak-vtables"
34 class OutgoingAsyncBase;
36 class CollocatedRequestHandler;
40 AsyncStatusQueued = 0,
42 AsyncStatusInvokeSentCallback = 2
45 class ICE_API OutgoingAsyncCompletionCallback
48 virtual ~OutgoingAsyncCompletionCallback();
52 virtual bool handleSent(
bool done,
bool alreadySent)
noexcept = 0;
55 virtual bool handleException(std::exception_ptr)
noexcept = 0;
59 virtual bool handleResponse(
bool) = 0;
61 virtual void handleInvokeSent(
bool, OutgoingAsyncBase*)
const = 0;
62 virtual void handleInvokeException(std::exception_ptr, OutgoingAsyncBase*)
const = 0;
63 virtual void handleInvokeResponse(
bool, OutgoingAsyncBase*)
const = 0;
71 class ICE_API OutgoingAsyncBase :
public virtual OutgoingAsyncCompletionCallback,
72 public std::enable_shared_from_this<OutgoingAsyncBase>
76 virtual bool exception(std::exception_ptr);
77 virtual bool response();
79 void invokeSentAsync();
80 void invokeExceptionAsync();
81 void invokeResponseAsync();
84 void invokeException();
85 void invokeResponse();
87 virtual void cancelable(
const IceInternal::CancellationHandlerPtr&);
95 Ice::OutputStream* getOs() {
return &_os; }
97 Ice::InputStream* getIs() {
return &_is; }
100 OutgoingAsyncBase(
const InstancePtr&);
103 bool exceptionImpl(std::exception_ptr);
104 bool responseImpl(
bool,
bool);
106 void cancel(std::exception_ptr);
108 void warning(std::string_view callbackName, std::exception_ptr eptr)
const;
114 virtual IceInternal::InvocationObserver& getObserver() {
return _observer; }
116 const InstancePtr _instance;
118 bool _sentSynchronously{
false};
119 bool _doneInSent{
false};
120 unsigned char _state{0};
123 using Lock = std::lock_guard<std::mutex>;
125 std::exception_ptr _ex;
126 std::exception_ptr _cancellationException;
128 InvocationObserver _observer;
129 ObserverHelperT<Ice::Instrumentation::ChildInvocationObserver> _childObserver;
131 Ice::OutputStream _os;
132 Ice::InputStream _is;
134 CancellationHandlerPtr _cancellationHandler;
136 static const unsigned char OK;
137 static const unsigned char Sent;
140 using OutgoingAsyncBasePtr = std::shared_ptr<OutgoingAsyncBase>;
148 class ICE_API ProxyOutgoingAsyncBase :
public OutgoingAsyncBase,
public TimerTask
151 virtual AsyncStatus invokeRemote(
const Ice::ConnectionIPtr&,
bool,
bool) = 0;
152 virtual AsyncStatus invokeCollocated(CollocatedRequestHandler*) = 0;
154 bool exception(std::exception_ptr)
override;
156 void retryException();
162 void abort(std::exception_ptr);
164 std::shared_ptr<ProxyOutgoingAsyncBase> shared_from_this()
166 return std::static_pointer_cast<ProxyOutgoingAsyncBase>(OutgoingAsyncBase::shared_from_this());
170 ProxyOutgoingAsyncBase(Ice::ObjectPrx);
171 ~ProxyOutgoingAsyncBase()
override;
173 void invokeImpl(
bool);
175 bool exceptionImpl(std::exception_ptr);
176 bool responseImpl(
bool,
bool);
178 void runTimerTask()
override;
180 const Ice::ObjectPrx _proxy;
181 RequestHandlerPtr _handler;
185 int handleRetryAfterException(std::exception_ptr);
186 int checkRetryAfterException(std::exception_ptr);
192 using ProxyOutgoingAsyncBasePtr = std::shared_ptr<ProxyOutgoingAsyncBase>;
197 class ICE_API OutgoingAsync :
public ProxyOutgoingAsyncBase
200 OutgoingAsync(Ice::ObjectPrx,
bool);
204 bool sent()
override;
205 bool response()
override;
207 AsyncStatus invokeRemote(
const Ice::ConnectionIPtr&,
bool,
bool)
override;
208 AsyncStatus invokeCollocated(CollocatedRequestHandler*)
override;
210 void abort(std::exception_ptr);
211 void invoke(std::string_view);
215 std::optional<Ice::FormatType>,
217 const std::function<
void(Ice::OutputStream*)>&);
218 void throwUserException();
220 Ice::OutputStream* startWriteParams(std::optional<Ice::FormatType> format)
222 _os.startEncapsulation(_encoding, format);
225 void endWriteParams() { _os.endEncapsulation(); }
226 void writeEmptyParams() { _os.writeEmptyEncapsulation(_encoding); }
227 void writeParamEncaps(
const std::byte* encaps, std::int32_t size)
231 _os.writeEmptyEncapsulation(_encoding);
235 _os.writeEncapsulation(encaps, size);
240 const Ice::EncodingVersion _encoding;
245 using OutgoingAsyncPtr = std::shared_ptr<OutgoingAsync>;
247 class ICE_API LambdaInvoke :
public virtual OutgoingAsyncCompletionCallback
250 LambdaInvoke(std::function<
void(std::exception_ptr)> exception, std::function<
void(
bool)> sent)
251 : _exception(std::move(exception)),
252 _sent(std::move(sent))
257 bool handleSent(
bool,
bool)
noexcept final;
258 bool handleException(std::exception_ptr)
noexcept final;
259 bool handleResponse(
bool)
final;
261 void handleInvokeSent(
bool, OutgoingAsyncBase*)
const final;
262 void handleInvokeException(std::exception_ptr, OutgoingAsyncBase*)
const final;
263 void handleInvokeResponse(
bool, OutgoingAsyncBase*)
const final;
265 std::function<void(std::exception_ptr)> _exception;
266 std::function<void(
bool)> _sent;
267 std::function<void(
bool)> _response;
270 template<
typename R>
class PromiseInvoke :
public virtual OutgoingAsyncCompletionCallback
273 [[nodiscard]] std::future<R> getFuture() {
return _promise.get_future(); }
276 bool handleSent(
bool,
bool)
noexcept override {
return false; }
278 bool handleException(std::exception_ptr ex)
noexcept final
280 _promise.set_exception(ex);
284 bool handleResponse(
bool ok)
final
290 void handleInvokeSent(
bool, OutgoingAsyncBase*)
const final { assert(
false); }
292 void handleInvokeException(std::exception_ptr, OutgoingAsyncBase*)
const final { assert(
false); }
294 void handleInvokeResponse(
bool, OutgoingAsyncBase*)
const final { assert(
false); }
296 std::promise<R> _promise;
297 std::function<void(
bool)> _response;
300 template<
typename T>
class OutgoingAsyncT :
public OutgoingAsync
303 using OutgoingAsync::OutgoingAsync;
306 std::string_view operation,
308 std::optional<Ice::FormatType> format,
310 const std::function<
void(Ice::OutputStream*)>& write,
313 _read = [](Ice::InputStream* stream)
319 _userException = std::move(userException);
320 OutgoingAsync::invoke(operation, mode, format, ctx, write);
324 std::string_view operation,
326 std::optional<Ice::FormatType> format,
328 const std::function<
void(Ice::OutputStream*)>& write,
330 std::function<T(Ice::InputStream*)> read)
332 _read = std::move(read);
333 _userException = std::move(userException);
334 OutgoingAsync::invoke(operation, mode, format, ctx, write);
338 std::function<T(Ice::InputStream*)> _read;
341 template<>
class OutgoingAsyncT<void> :
public OutgoingAsync
344 using OutgoingAsync::OutgoingAsync;
347 std::string_view operation,
349 std::optional<Ice::FormatType> format,
351 const std::function<
void(Ice::OutputStream*)>& write,
354 _userException = std::move(userException);
355 OutgoingAsync::invoke(operation, mode, format, ctx, write);
359 template<
typename R>
class LambdaOutgoing :
public OutgoingAsyncT<R>,
public LambdaInvoke
363 Ice::ObjectPrx proxy,
364 std::function<
void(R)> response,
365 std::function<
void(std::exception_ptr)> ex,
366 std::function<
void(
bool)> sent)
367 : OutgoingAsyncT<R>(std::move(proxy), false),
368 LambdaInvoke(std::move(ex), std::move(sent))
370 _response = [
this, response = std::move(response)](
bool ok)
374 this->throwUserException();
379 this->_is.startEncapsulation();
380 R v = this->_read(&this->_is);
381 this->_is.endEncapsulation();
384 response(std::move(v));
388 this->warning(
"response", std::current_exception());
395 template<>
class LambdaOutgoing<void> :
public OutgoingAsyncT<void>,
public LambdaInvoke
399 Ice::ObjectPrx proxy,
400 std::function<
void()> response,
401 std::function<
void(std::exception_ptr)> ex,
402 std::function<
void(
bool)> sent)
403 : OutgoingAsyncT<void>(std::move(proxy), false),
404 LambdaInvoke(std::move(ex), std::move(sent))
406 _response = [
this, response = std::move(response)](
bool ok)
410 this->throwUserException();
414 if (!this->_is.b.empty())
416 this->_is.skipEmptyEncapsulation();
424 this->warning(
"response", std::current_exception());
431 template<
typename R>
class PromiseOutgoing :
public OutgoingAsyncT<R>,
public PromiseInvoke<R>
434 PromiseOutgoing(Ice::ObjectPrx proxy,
bool sync) : OutgoingAsyncT<R>(std::move(proxy), sync)
436 this->_response = [
this](
bool ok)
441 this->_is.startEncapsulation();
442 R v = this->_read(&this->_is);
443 this->_is.endEncapsulation();
444 this->_promise.set_value(std::move(v));
448 this->throwUserException();
454 template<>
class PromiseOutgoing<void> :
public OutgoingAsyncT<void>,
public PromiseInvoke<void>
457 PromiseOutgoing(Ice::ObjectPrx proxy,
bool sync) : OutgoingAsyncT<void>(std::move(proxy), sync)
459 this->_response = [&](
bool ok)
461 if (this->_is.b.empty())
468 this->_promise.set_value();
472 this->_is.skipEmptyEncapsulation();
473 this->_promise.set_value();
477 this->throwUserException();
482 bool handleSent(
bool done,
bool)
noexcept final
486 PromiseInvoke<void>::_promise.set_value();
492 template<
typename R,
typename Obj,
typename Fn,
typename... Args>
493 [[nodiscard]]
inline std::future<R> makePromiseOutgoing(
bool sync, Obj obj, Fn fn, Args&&... args)
495 auto outAsync = std::make_shared<PromiseOutgoing<R>>(*obj, sync);
496 (obj->*fn)(outAsync, std::forward<Args>(args)...);
497 return outAsync->getFuture();
500 template<
typename R,
typename Re,
typename E,
typename S,
typename Obj,
typename Fn,
typename... Args>
501 [[nodiscard]]
inline std::function<void()> makeLambdaOutgoing(Re r, E e, S s, Obj obj, Fn fn, Args&&... args)
503 auto outAsync = std::make_shared<LambdaOutgoing<R>>(*obj, std::move(r), std::move(e), std::move(s));
504 (obj->*fn)(outAsync, std::forward<Args>(args)...);
505 return [outAsync]() { outAsync->cancel(); };
511#elif defined(__clang__)
512# 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.