iceoryx2
C++ Bindings
Loading...
Searching...
No Matches
active_request.hpp
Go to the documentation of this file.
1// Copyright (c) 2025 Contributors to the Eclipse Foundation
2//
3// See the NOTICE file(s) distributed with this work for additional
4// information regarding copyright ownership.
5//
6// This program and the accompanying materials are made available under the
7// terms of the Apache Software License 2.0 which is available at
8// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license
9// which is available at https://opensource.org/licenses/MIT.
10//
11// SPDX-License-Identifier: Apache-2.0 OR MIT
12
13#ifndef IOX2_ACTIVE_REQUEST_HPP
14#define IOX2_ACTIVE_REQUEST_HPP
15
16#include "internal/helper.hpp"
17#include "iox2/bb/expected.hpp"
18#include "iox2/deployment/iceoryx2_cxx_feature_flags.hpp"
20#include "iox2/marker.hpp"
21#include "iox2/payload_info.hpp"
23#include "iox2/service_type.hpp"
24
25#if IOX2_FEATURE_FLATBUFFERS
26#include <flatbuffers/flatbuffers.h>
27#endif // IOX2_FEATURE_FLATBUFFERS
28
29#include <type_traits>
30
31namespace iox2 {
36template <ServiceType Service,
37 typename RequestPayload,
38 typename RequestUserHeader,
39 typename ResponsePayload,
40 typename ResponseUserHeader>
42 using ValueType = typename PayloadInfo<RequestPayload>::ValueType;
43
44 public:
45 ActiveRequest(ActiveRequest&& rhs) noexcept;
46 auto operator=(ActiveRequest&& rhs) noexcept -> ActiveRequest&;
47 ~ActiveRequest() noexcept;
48
49 ActiveRequest(const ActiveRequest&) = delete;
50 auto operator=(const ActiveRequest&) noexcept -> ActiveRequest& = delete;
51
53 template <typename T = ResponsePayload, typename = std::enable_if_t<!bb::IsSlice<T>::VALUE, void>>
55
57 template <typename T = ResponsePayload, typename = std::enable_if_t<bb::IsSlice<T>::VALUE, void>>
58 auto loan_slice_uninit(uint64_t number_of_elements)
60
63 template <typename T = RequestPayload, typename = std::enable_if_t<!bb::IsSlice<T>::VALUE, void>>
64 auto send_copy(const ResponsePayload& payload) const -> bb::Expected<void, SendError>;
65
68 template <typename T = RequestPayload, typename = std::enable_if_t<bb::IsSlice<T>::VALUE, void>>
70
72 template <typename T = RequestPayload, typename = std::enable_if_t<!bb::IsSlice<T>::VALUE, void>>
73 auto payload() const -> const T&;
74
76 template <typename T = RequestPayload, typename = std::enable_if_t<bb::IsSlice<T>::VALUE, void>>
77 auto payload() const -> bb::ImmutableSlice<ValueType>;
78
80 template <typename T = RequestUserHeader,
81 typename = std::enable_if_t<!std::is_same<void, RequestUserHeader>::value, T>>
82 auto user_header() const -> const T&;
83
85 auto header() const -> RequestHeader;
86
88 auto origin() const -> UniqueClientId;
89
92 auto is_connected() const -> bool;
93
98 auto has_disconnect_hint() const -> bool;
99
102 template <typename T = ResponsePayload, typename = std::enable_if_t<!bb::IsSlice<T>::VALUE, void>>
103 auto loan() -> bb::Expected<ResponseMut<Service, ResponsePayload, ResponseUserHeader>, LoanError>;
104
107 template <typename T = ResponsePayload, typename = std::enable_if_t<bb::IsSlice<T>::VALUE, void>>
108 auto loan_slice(uint64_t number_of_elements)
109 -> bb::Expected<ResponseMut<Service, ResponsePayload, ResponseUserHeader>, LoanError>;
110
111#if IOX2_FEATURE_FLATBUFFERS
113 template <typename T = RequestPayload, typename = std::enable_if_t<has_flatbuffer_marker<T>(), void>>
114 auto payload_bytes() const -> bb::ImmutableSlice<uint8_t>;
115
117 template <typename T = RequestPayload, typename = std::enable_if_t<has_flatbuffer_marker<T>(), void>>
118 auto payload_root() const -> const typename T::ValueType*;
119
120 template <typename T = ResponsePayload, typename = std::enable_if_t<has_flatbuffer_marker<T>(), void>>
121 auto loan_flatbuffer() -> bb::Expected<ResponseMutUninit<Service, ResponsePayload, ResponseUserHeader>, LoanError>;
122#endif // IOX2_FEATURE_FLATBUFFERS
123
124 private:
125 template <ServiceType, typename, typename, typename, typename>
126 friend class Server;
127
128 explicit ActiveRequest(iox2_active_request_h handle) noexcept;
129
130 void drop();
131
132 iox2_active_request_h m_handle = nullptr;
133};
134
135template <ServiceType Service,
136 typename RequestPayload,
137 typename RequestUserHeader,
138 typename ResponsePayload,
139 typename ResponseUserHeader>
144
145template <ServiceType Service,
146 typename RequestPayload,
147 typename RequestUserHeader,
148 typename ResponsePayload,
149 typename ResponseUserHeader>
151 ActiveRequest&& rhs) noexcept -> ActiveRequest& {
152 if (this != &rhs) {
153 drop();
154 m_handle = rhs.m_handle;
155 rhs.m_handle = nullptr;
156 }
157
158 return *this;
159}
160
161template <ServiceType Service,
162 typename RequestPayload,
163 typename RequestUserHeader,
164 typename ResponsePayload,
165 typename ResponseUserHeader>
170
171#if IOX2_FEATURE_FLATBUFFERS
172template <ServiceType Service,
173 typename RequestPayload,
174 typename RequestUserHeader,
175 typename ResponsePayload,
176 typename ResponseUserHeader>
177template <typename T, typename>
178inline auto
180 -> bb::ImmutableSlice<uint8_t> {
181 const void* ptr = nullptr;
182 size_t number_of_elements = 0;
183
184 iox2_active_request_payload(&m_handle, &ptr, &number_of_elements);
185 auto payload_offset = header().payload_offset();
186 auto payload_len = header().number_of_elements();
187
188 return bb::ImmutableSlice<uint8_t>(static_cast<const uint8_t*>(ptr) + payload_offset, payload_len - payload_offset);
189}
190
191template <ServiceType Service,
192 typename RequestPayload,
193 typename RequestUserHeader,
194 typename ResponsePayload,
195 typename ResponseUserHeader>
196template <typename T, typename>
197inline auto
199 -> const typename T::ValueType* {
200 return flatbuffers::GetRoot<typename T::ValueType>(payload_bytes().data());
201}
202#endif // IOX2_FEATURE_FLATBUFFERS
203
204template <ServiceType Service,
205 typename RequestPayload,
206 typename RequestUserHeader,
207 typename ResponsePayload,
208 typename ResponseUserHeader>
209template <typename T, typename>
210inline auto
213 constexpr uint64_t NUMBER_OF_ELEMENTS = 1;
215 auto result = iox2_active_request_loan_slice_uninit(
216 &m_handle, &response.m_response.m_response, &response.m_response.m_handle, NUMBER_OF_ELEMENTS);
218 if (result == IOX2_OK) {
219 return response;
220 }
221 return bb::err(bb::into<LoanError>(result));
222}
223
224template <ServiceType Service,
225 typename RequestPayload,
226 typename RequestUserHeader,
227 typename ResponsePayload,
228 typename ResponseUserHeader>
229template <typename T, typename>
230inline auto
232 uint64_t number_of_elements)
235 auto result = iox2_active_request_loan_slice_uninit(
236 &m_handle, &response.m_response.m_response, &response.m_response.m_handle, number_of_elements);
238 if (result == IOX2_OK) {
239 return response;
240 }
241 return bb::err(bb::into<LoanError>(result));
242}
243
244template <ServiceType Service,
245 typename RequestPayload,
246 typename RequestUserHeader,
247 typename ResponsePayload,
248 typename ResponseUserHeader>
249template <typename T, typename>
251 const ResponsePayload& payload) const -> bb::Expected<void, SendError> {
252 static_assert(std::is_trivially_copyable<ResponsePayload>::value,
253 "The server supports only trivially copyable response payload types.");
254 constexpr uint64_t NUMBER_OF_ELEMENTS = 1;
255
256 auto result = iox2_active_request_send_copy(
257 &m_handle, static_cast<const void*>(&payload), sizeof(ResponsePayload), NUMBER_OF_ELEMENTS);
258 if (result == IOX2_OK) {
259 return {};
260 }
261 return bb::err(bb::into<SendError>(result));
262}
263
264template <ServiceType Service,
265 typename RequestPayload,
266 typename RequestUserHeader,
267 typename ResponsePayload,
268 typename ResponseUserHeader>
269template <typename T, typename>
270inline auto
273 static_assert(std::is_trivially_copyable<ValueType>::value,
274 "The server supports only trivially copyable response payload types.");
275
276 auto result = iox2_active_request_send_copy(
277 &m_handle, payload.data(), sizeof(typename ResponsePayload::ValueType), payload.number_of_elements());
278 if (result == IOX2_OK) {
279 return {};
280 }
281 return bb::err(bb::into<SendError>(result));
282}
283
284template <ServiceType Service,
285 typename RequestPayload,
286 typename RequestUserHeader,
287 typename ResponsePayload,
288 typename ResponseUserHeader>
289template <typename T, typename>
290inline auto
292 -> const T& {
293 const void* ptr = nullptr;
294 iox2_active_request_payload(&m_handle, &ptr, nullptr);
295 return *static_cast<const T*>(ptr);
296}
297
298template <ServiceType Service,
299 typename RequestPayload,
300 typename RequestUserHeader,
301 typename ResponsePayload,
302 typename ResponseUserHeader>
303template <typename T, typename>
304inline auto
306 -> bb::ImmutableSlice<ValueType> {
307 const void* ptr = nullptr;
308 size_t number_of_elements = 0;
309
310 iox2_active_request_payload(&m_handle, &ptr, &number_of_elements);
311
312 // for the custom payload marker, the slice length is the
313 // runtime payload byte size
314 auto length = number_of_elements;
315 if (std::is_same<ValueType, CustomPayloadMarker>::value) {
316 length = iox2_active_request_payload_number_of_bytes(&m_handle);
317 }
318
319 return bb::ImmutableSlice<ValueType>(static_cast<const ValueType*>(ptr), length);
320}
321
322template <ServiceType Service,
323 typename RequestPayload,
324 typename RequestUserHeader,
325 typename ResponsePayload,
326 typename ResponseUserHeader>
327template <typename T, typename>
328inline auto
330 -> const T& {
331 const void* ptr = nullptr;
332 iox2_active_request_user_header(&m_handle, &ptr);
333 return *static_cast<const T*>(ptr);
334}
335
336template <ServiceType Service,
337 typename RequestPayload,
338 typename RequestUserHeader,
339 typename ResponsePayload,
340 typename ResponseUserHeader>
341inline auto
343 -> RequestHeader {
344 iox2_request_header_h header_handle = nullptr;
345 iox2_active_request_header(&m_handle, nullptr, &header_handle);
346 return RequestHeader { header_handle };
347}
348
349template <ServiceType Service,
350 typename RequestPayload,
351 typename RequestUserHeader,
352 typename ResponsePayload,
353 typename ResponseUserHeader>
354inline auto
359
360template <ServiceType Service,
361 typename RequestPayload,
362 typename RequestUserHeader,
363 typename ResponsePayload,
364 typename ResponseUserHeader>
365inline auto
367 -> bool {
368 return iox2_active_request_is_connected(&m_handle);
369}
370
371template <ServiceType Service,
372 typename RequestPayload,
373 typename RequestUserHeader,
374 typename ResponsePayload,
375 typename ResponseUserHeader>
376inline auto
378 const -> bool {
379 return iox2_active_request_has_disconnect_hint(&m_handle);
380}
381
382template <ServiceType Service,
383 typename RequestPayload,
384 typename RequestUserHeader,
385 typename ResponsePayload,
386 typename ResponseUserHeader>
387template <typename T, typename>
390 auto response = loan_uninit();
391 if (!response.has_value()) {
392 return bb::err(response.error());
393 }
394
395 new (&response->payload_mut()) ResponsePayload();
396 return assume_init(std::move(*response));
397}
398
399template <ServiceType Service,
400 typename RequestPayload,
401 typename RequestUserHeader,
402 typename ResponsePayload,
403 typename ResponseUserHeader>
404template <typename T, typename>
407 auto response_uninit = loan_slice_uninit(number_of_elements);
408 if (!response_uninit.has_value()) {
409 return bb::err(response_uninit.error());
410 }
411
412 auto response_init = std::move(response_uninit.value());
413 for (auto& item : response_init.payload_mut()) {
414 new (&item) ValueType();
415 }
416
417 return assume_init(std::move(response_init));
418}
419
420template <ServiceType Service,
421 typename RequestPayload,
422 typename RequestUserHeader,
423 typename ResponsePayload,
424 typename ResponseUserHeader>
426 iox2_active_request_h handle) noexcept
427 : m_handle(handle) {
428}
429
430template <ServiceType Service,
431 typename RequestPayload,
432 typename RequestUserHeader,
433 typename ResponsePayload,
434 typename ResponseUserHeader>
435inline void ActiveRequest<Service, RequestPayload, RequestUserHeader, ResponsePayload, ResponseUserHeader>::drop() {
436 if (m_handle != nullptr) {
437 iox2_active_request_drop(m_handle);
438 m_handle = nullptr;
439 }
440}
441
442#if IOX2_FEATURE_FLATBUFFERS
443template <ServiceType Service,
444 typename RequestPayload,
445 typename RequestUserHeader,
446 typename ResponsePayload,
447 typename ResponseUserHeader>
448template <typename T, typename>
449inline auto
453
454 auto result = iox2_active_request_loan_slice_uninit(
455 &m_handle, &response.m_response.m_response, &response.m_response.m_handle, 1);
456
457 if (result != IOX2_OK) {
458 return bb::err(iox2::bb::into<LoanError>(result));
459 }
460
461 iox2_resizable_memory_response_h resizable_memory_handle {};
462 iox2_response_mut_create_resizable_memory(&response.m_response.m_handle, nullptr, &resizable_memory_handle);
463
464 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) The FlatBufferBuilder takes the ownership and the external interface requires a raw pointer.
465 response.m_memory = new internal::ResizableMemoryResponse<Service>(resizable_memory_handle);
466
467 auto initial_size = response.m_memory->len();
468 response.m_flatbuffer_builder = flatbuffers::FlatBufferBuilder(initial_size, response.m_memory, true);
469
470 return std::move(response);
471}
472#endif // IOX2_FEATURE_FLATBUFFERS
473} // namespace iox2
474
475#endif
auto operator=(const ActiveRequest &) noexcept -> ActiveRequest &=delete
auto loan_uninit() -> bb::Expected< ResponseMutUninit< Service, ResponsePayload, ResponseUserHeader >, LoanError >
Loans uninitialized memory for a [ResponseMutUninit] where the user can write its payload to.
auto origin() const -> UniqueClientId
Returns the [UniqueClientId] of the [Client].
auto is_connected() const -> bool
auto header() const -> RequestHeader
Returns a reference to the [RequestHeader] of the received [RequestMut].
auto loan_flatbuffer() -> bb::Expected< ResponseMutUninit< Service, ResponsePayload, ResponseUserHeader >, LoanError >
auto has_disconnect_hint() const -> bool
auto payload_bytes() const -> bb::ImmutableSlice< uint8_t >
Returns the serialized flatbuffer data as bytes.
auto loan() -> bb::Expected< ResponseMut< Service, ResponsePayload, ResponseUserHeader >, LoanError >
auto user_header() const -> const T &
Returns a reference to the user_header of the received [RequestMut].
auto loan_slice_uninit(uint64_t number_of_elements) -> bb::Expected< ResponseMutUninit< Service, ResponsePayload, ResponseUserHeader >, LoanError >
Loans uninitialized memory for a [ResponseMutUninit] where the user can write its payload to.
auto send_slice_copy(const bb::ImmutableSlice< ValueType > &payload) const -> bb::Expected< void, SendError >
auto loan_slice(uint64_t number_of_elements) -> bb::Expected< ResponseMut< Service, ResponsePayload, ResponseUserHeader >, LoanError >
auto send_copy(const ResponsePayload &payload) const -> bb::Expected< void, SendError >
ActiveRequest(const ActiveRequest &)=delete
ActiveRequest(ActiveRequest &&rhs) noexcept
auto payload() const -> const T &
Returns a reference to the payload of the received [RequestMut].
auto operator=(ActiveRequest &&rhs) noexcept -> ActiveRequest &
auto payload_root() const -> const typename T::ValueType *
Returns the root of the flatbuffer.
Request header used by [MessagingPattern::RequestResponse].
The system-wide unique id of a [Client].
A class representing a slice of contiguous elements of type T.
Definition slice.hpp:31
Internal helper class to handle dynamic memory allocations used in e.g. flatbuffers.
constexpr auto err(const E &error) -> Unexpected< E >
Definition expected.hpp:33
iox2::bb::variation::Expected< T, E > Expected
Definition expected.hpp:22
constexpr auto has_flatbuffer_marker() -> bool
Definition marker.hpp:53
auto assume_init(RequestMutUninit< Service, RequestPayload, RequestUserHeader, ResponsePayload, ResponseUserHeader > &&self) -> RequestMut< Service, RequestPayload, RequestUserHeader, ResponsePayload, ResponseUserHeader >
auto loan_uninit(EntryHandleMut< S, KeyType, ValueType > &&self) -> EntryValueUninit< S, KeyType, ValueType >
static void placement_default(S &payload)
Definition helper.hpp:22