Ice 3.8
C++ API Reference
Loading...
Searching...
No Matches
AsyncResponseHandler.h
1// Copyright (c) ZeroC, Inc.
2
3#ifndef ICE_ASYNC_RESPONSE_HANDLER_H
4#define ICE_ASYNC_RESPONSE_HANDLER_H
5
6#include "Current.h"
7#include "LocalExceptions.h"
8#include "OutgoingResponse.h"
9
10#include <atomic>
11
12namespace IceInternal
13{
14 // This class helps with the implementation of the AMD response and exception callbacks. It allows the dispatch
15 // thread and these two callbacks to share the same sendResponse and Current objects, and ensures sendResponse is
16 // called exactly once.
17 class AsyncResponseHandler final
18 {
19 public:
20 // This class typically holds a _copy_ of the incoming request current object.
21 AsyncResponseHandler(std::function<void(Ice::OutgoingResponse)> sendResponse, Ice::Current current)
22 : _sendResponse(std::move(sendResponse)),
23 _current(std::move(current))
24 {
25 }
26
27 void sendEmptyResponse() noexcept
28 {
29 if (!_responseSent.test_and_set())
30 {
31 _sendResponse(makeEmptyOutgoingResponse(_current));
32 }
33 // else we ignore this call.
34 }
35
36 void sendResponse(Ice::MarshaledResult marshaledResult) noexcept
37 {
38 if (!_responseSent.test_and_set())
39 {
40 _sendResponse(Ice::OutgoingResponse{std::move(marshaledResult).outputStream(), _current});
41 }
42 // else we ignore this call.
43 }
44
45 void sendResponse(bool ok, std::pair<const std::byte*, const std::byte*> encaps) noexcept
46 {
47 if (!_responseSent.test_and_set())
48 {
49 _sendResponse(makeOutgoingResponse(ok, encaps, _current));
50 }
51 // else we ignore this call.
52 }
53
54 void sendResponse(
55 const std::function<void(Ice::OutputStream*)>& marshal,
56 std::optional<Ice::FormatType> format = std::nullopt) noexcept
57 {
58 // It is critical to only call the _sendResponse function only once. Calling it multiple times results in an
59 // incorrect dispatch count.
60 if (!_responseSent.test_and_set())
61 {
62 _sendResponse(makeOutgoingResponse(marshal, _current, format));
63 }
64 // else we ignore this call.
65 }
66
67 void sendException(std::exception_ptr ex) noexcept
68 {
69 if (!_responseSent.test_and_set())
70 {
71 _sendResponse(makeOutgoingResponse(ex, _current));
72 }
73 // else we ignore this call.
74 }
75
76 [[nodiscard]] const Ice::Current& current() const noexcept { return _current; }
77
78 private:
79 const std::function<void(Ice::OutgoingResponse)> _sendResponse;
80 const Ice::Current _current;
81 std::atomic_flag _responseSent = ATOMIC_FLAG_INIT;
82 };
83}
84
85#endif
OutgoingResponse makeOutgoingResponse(const std::function< void(OutputStream *)> &marshal, const Current &current, std::optional< FormatType > format=std::nullopt) noexcept
Creates an OutgoingResponse object with ReplyStatus::Ok.
OutgoingResponse makeEmptyOutgoingResponse(const Current &current) noexcept
Creates an OutgoingResponse object with ReplyStatus::Ok and an empty payload.