iceoryx2
C++ Bindings
Loading...
Searching...
No Matches
client.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_CLIENT_HPP
14#define IOX2_CLIENT_HPP
15
16#include "iox2/bb/expected.hpp"
17#include "iox2/bb/slice.hpp"
18#include "iox2/deployment/iceoryx2_cxx_feature_flags.hpp"
20#include "iox2/payload_info.hpp"
21#include "iox2/port_name.hpp"
23#include "iox2/service_type.hpp"
25
26namespace iox2 {
28template <ServiceType Service,
29 typename RequestPayload,
30 typename RequestUserHeader,
31 typename ResponsePayload,
32 typename ResponseUserHeader>
33class Client {
34 using ValueType = typename PayloadInfo<RequestPayload>::ValueType;
35
36 public:
37 Client(Client&& rhs) noexcept;
38 auto operator=(Client&& rhs) noexcept -> Client&;
39 ~Client() noexcept;
40
41 Client(const Client&) noexcept = delete;
42 auto operator=(const Client&) noexcept -> Client& = delete;
43
45 auto id() const -> UniqueClientId;
46
48 auto name() const -> PortNameView;
49
53
55 auto max_active_requests() const -> uint64_t;
56
58 template <typename T = RequestPayload, typename = std::enable_if_t<bb::IsSlice<T>::VALUE, void>>
59 auto initial_max_slice_len() const -> uint64_t;
60
64 template <typename T = RequestPayload, typename = std::enable_if_t<!bb::IsSlice<T>::VALUE, void>>
65 auto send_copy(const RequestPayload& payload) const -> bb::Expected<
66 PendingResponse<Service, RequestPayload, RequestUserHeader, ResponsePayload, ResponseUserHeader>,
68
72 template <typename T = RequestPayload, typename = std::enable_if_t<bb::IsSlice<T>::VALUE, void>>
73 auto send_slice_copy(bb::ImmutableSlice<ValueType>& payload) const -> bb::Expected<
74 PendingResponse<Service, RequestPayload, RequestUserHeader, ResponsePayload, ResponseUserHeader>,
76
79 template <typename T = RequestPayload, typename = std::enable_if_t<!bb::IsSlice<T>::VALUE, void>>
80 auto loan_uninit() -> bb::Expected<
81 RequestMutUninit<Service, RequestPayload, RequestUserHeader, ResponsePayload, ResponseUserHeader>,
82 LoanError>;
83
86 template <typename T = RequestPayload, typename = std::enable_if_t<bb::IsSlice<T>::VALUE, void>>
87 auto loan_slice_uninit(uint64_t number_of_elements)
88 -> bb::Expected<RequestMutUninit<Service, T, RequestUserHeader, ResponsePayload, ResponseUserHeader>,
89 LoanError>;
90
94 template <typename T = RequestPayload, typename = std::enable_if_t<!bb::IsSlice<T>::VALUE, void>>
95 auto loan()
96 -> bb::Expected<RequestMut<Service, T, RequestUserHeader, ResponsePayload, ResponseUserHeader>, LoanError>;
97
101 template <typename T = RequestPayload, typename = std::enable_if_t<bb::IsSlice<T>::VALUE, void>>
102 auto loan_slice(uint64_t number_of_elements)
103 -> bb::Expected<RequestMut<Service, T, RequestUserHeader, ResponsePayload, ResponseUserHeader>, LoanError>;
104
105#if IOX2_FEATURE_FLATBUFFERS
107 template <typename T = RequestPayload, typename = std::enable_if_t<has_flatbuffer_marker<T>(), void>>
110 LoanError>;
111#endif // IOX2_FEATURE_FLATBUFFERS
112
113 private:
114 template <ServiceType, typename, typename, typename, typename>
115 friend class PortFactoryClient;
116
117 explicit Client(iox2_client_h handle) noexcept;
118
119 void drop();
120
121 iox2_client_h m_handle = nullptr;
122};
123
124template <ServiceType Service,
125 typename RequestPayload,
126 typename RequestUserHeader,
127 typename ResponsePayload,
128 typename ResponseUserHeader>
133
134template <ServiceType Service,
135 typename RequestPayload,
136 typename RequestUserHeader,
137 typename ResponsePayload,
138 typename ResponseUserHeader>
140 Client&& rhs) noexcept -> Client& {
141 if (this != &rhs) {
142 drop();
143 m_handle = rhs.m_handle;
144 rhs.m_handle = nullptr;
145 }
146
147 return *this;
148}
149
150template <ServiceType Service,
151 typename RequestPayload,
152 typename RequestUserHeader,
153 typename ResponsePayload,
154 typename ResponseUserHeader>
158
159template <ServiceType Service,
160 typename RequestPayload,
161 typename RequestUserHeader,
162 typename ResponsePayload,
163 typename ResponseUserHeader>
165 -> UniqueClientId {
166 iox2_unique_client_id_h id_handle = nullptr;
167 iox2_client_id(&m_handle, nullptr, &id_handle);
168 return UniqueClientId { id_handle };
169}
170
171template <ServiceType Service,
172 typename RequestPayload,
173 typename RequestHeader,
174 typename ResponsePayload,
175 typename ResponseHeader>
177 -> PortNameView {
178 const auto* port_name_ptr = iox2_client_name(&m_handle);
179 return PortNameView::from_native_ptr(port_name_ptr);
180}
181
182template <ServiceType Service,
183 typename RequestPayload,
184 typename RequestUserHeader,
185 typename ResponsePayload,
186 typename ResponseUserHeader>
187inline auto
190 return iox2::bb::into<BackpressureStrategy>(static_cast<int>(iox2_client_backpressure_strategy(&m_handle)));
191}
192
193template <ServiceType Service,
194 typename RequestPayload,
195 typename RequestUserHeader,
196 typename ResponsePayload,
197 typename ResponseUserHeader>
198inline auto
200 -> uint64_t {
201 return iox2_client_max_active_requests(&m_handle);
202}
203
204template <ServiceType Service,
205 typename RequestPayload,
206 typename RequestUserHeader,
207 typename ResponsePayload,
208 typename ResponseUserHeader>
209template <typename T, typename>
210inline auto
212 -> uint64_t {
213 return iox2_client_initial_max_slice_len(&m_handle);
214}
215
216template <ServiceType Service,
217 typename RequestPayload,
218 typename RequestUserHeader,
219 typename ResponsePayload,
220 typename ResponseUserHeader>
221template <typename T, typename>
224 LoanError> {
225 constexpr uint64_t NUMBER_OF_ELEMENTS = 1;
227 auto result = iox2_client_loan_slice_uninit(
228 &m_handle, &request.m_request.m_request, &request.m_request.m_handle, NUMBER_OF_ELEMENTS);
230 if (result == IOX2_OK) {
231 return request;
232 }
233 return bb::err(bb::into<LoanError>(result));
234}
235
236template <ServiceType Service,
237 typename RequestPayload,
238 typename RequestUserHeader,
239 typename ResponsePayload,
240 typename ResponseUserHeader>
241template <typename T, typename>
243 uint64_t number_of_elements)
246 auto result = iox2_client_loan_slice_uninit(
247 &m_handle, &request.m_request.m_request, &request.m_request.m_handle, number_of_elements);
249 if (result == IOX2_OK) {
250 return request;
251 }
252 return bb::err(bb::into<LoanError>(result));
253}
254
255template <ServiceType Service,
256 typename RequestPayload,
257 typename RequestUserHeader,
258 typename ResponsePayload,
259 typename ResponseUserHeader>
260template <typename T, typename>
262 const RequestPayload& payload) const
265 static_assert(std::is_trivially_copyable<RequestPayload>::value,
266 "The client supports only trivially copyable request payload types.");
267
268 iox2_pending_response_h pending_response_handle {};
269 auto result = iox2_client_send_copy(
270 &m_handle, static_cast<const void*>(&payload), sizeof(RequestPayload), 1, nullptr, &pending_response_handle);
271
272 if (result == IOX2_OK) {
274 pending_response_handle);
275 }
276
277 return bb::err(bb::into<RequestSendError>(result));
278}
279
280template <ServiceType Service,
281 typename RequestPayload,
282 typename RequestUserHeader,
283 typename ResponsePayload,
284 typename ResponseUserHeader>
285template <typename T, typename>
287 bb::ImmutableSlice<ValueType>& payload) const
290 static_assert(std::is_trivially_copyable<ValueType>::value,
291 "The client supports only trivially copyable request payload types.");
292
293 iox2_pending_response_h pending_response_handle {};
294 auto result = iox2_client_send_copy(&m_handle,
295 payload.data(),
296 sizeof(typename RequestPayload::ValueType),
297 payload.number_of_elements(),
298 nullptr,
299 &pending_response_handle);
300
301 if (result == IOX2_OK) {
303 pending_response_handle);
304 }
305
306 return bb::err(bb::into<RequestSendError>(result));
307}
308
309template <ServiceType Service,
310 typename RequestPayload,
311 typename RequestUserHeader,
312 typename ResponsePayload,
313 typename ResponseUserHeader>
314template <typename T, typename>
317 auto request = loan_uninit();
318 if (!request.has_value()) {
319 return bb::err(request.error());
320 }
321
322 new (&request->payload_mut()) RequestPayload();
323 return assume_init(std::move(*request));
324}
325
326template <ServiceType Service,
327 typename RequestPayload,
328 typename RequestUserHeader,
329 typename ResponsePayload,
330 typename ResponseUserHeader>
331template <typename T, typename>
333 uint64_t number_of_elements)
335 auto request_uninit = loan_slice_uninit(number_of_elements);
336 if (!request_uninit.has_value()) {
337 return bb::err(request_uninit.error());
338 }
339
340 auto request_init = std::move(request_uninit.value());
341 for (auto& item : request_init.payload_mut()) {
342 new (&item) ValueType();
343 }
344
345 return assume_init(std::move(request_init));
346}
347
348template <ServiceType Service,
349 typename RequestPayload,
350 typename RequestUserHeader,
351 typename ResponsePayload,
352 typename ResponseUserHeader>
354 iox2_client_h handle) noexcept
355 : m_handle { handle } {
356}
357
358template <ServiceType Service,
359 typename RequestPayload,
360 typename RequestUserHeader,
361 typename ResponsePayload,
362 typename ResponseUserHeader>
363inline void Client<Service, RequestPayload, RequestUserHeader, ResponsePayload, ResponseUserHeader>::drop() {
364 if (m_handle != nullptr) {
365 iox2_client_drop(m_handle);
366 m_handle = nullptr;
367 }
368}
369
370#if IOX2_FEATURE_FLATBUFFERS
371template <ServiceType Service,
372 typename RequestPayload,
373 typename RequestUserHeader,
374 typename ResponsePayload,
375 typename ResponseUserHeader>
376template <typename T, typename>
379 LoanError> {
381
382 auto result =
383 iox2_client_loan_slice_uninit(&m_handle, &request.m_request.m_request, &request.m_request.m_handle, 1);
384
385 if (result != IOX2_OK) {
386 return bb::err(iox2::bb::into<LoanError>(result));
387 }
388
389 iox2_resizable_memory_request_h resizable_memory_handle {};
390 iox2_request_mut_create_resizable_memory(&request.m_request.m_handle, nullptr, &resizable_memory_handle);
391
392 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) The FlatBufferBuilder takes the ownership and the external interface requires a raw pointer.
393 request.m_memory = new internal::ResizableMemoryRequest<Service>(resizable_memory_handle);
394
395 auto initial_size = request.m_memory->len();
396 request.m_flatbuffer_builder = flatbuffers::FlatBufferBuilder(initial_size, request.m_memory, true);
397
398 return std::move(request);
399}
400#endif // IOX2_FEATURE_FLATBUFFERS
401
402
403} // namespace iox2
404
405#endif
Sends [RequestMut]s to a [Server] in a request-response based communication.
Definition client.hpp:33
auto loan_slice_uninit(uint64_t number_of_elements) -> bb::Expected< RequestMutUninit< Service, T, RequestUserHeader, ResponsePayload, ResponseUserHeader >, LoanError >
Definition client.hpp:242
Client(const Client &) noexcept=delete
auto backpressure_strategy() const -> BackpressureStrategy
Definition client.hpp:188
auto loan_slice(uint64_t number_of_elements) -> bb::Expected< RequestMut< Service, T, RequestUserHeader, ResponsePayload, ResponseUserHeader >, LoanError >
Definition client.hpp:332
auto send_slice_copy(bb::ImmutableSlice< ValueType > &payload) const -> bb::Expected< PendingResponse< Service, RequestPayload, RequestUserHeader, ResponsePayload, ResponseUserHeader >, RequestSendError >
Definition client.hpp:286
Client(Client &&rhs) noexcept
Definition client.hpp:129
auto operator=(const Client &) noexcept -> Client &=delete
auto loan_uninit() -> bb::Expected< RequestMutUninit< Service, RequestPayload, RequestUserHeader, ResponsePayload, ResponseUserHeader >, LoanError >
Definition client.hpp:222
auto loan_flatbuffer() -> bb::Expected< RequestMutUninit< Service, RequestPayload, RequestUserHeader, ResponsePayload, ResponseUserHeader >, LoanError >
Acquires a [RequestMutUninit] with an integrated flatbuffer builder.
Definition client.hpp:377
auto loan() -> bb::Expected< RequestMut< Service, T, RequestUserHeader, ResponsePayload, ResponseUserHeader >, LoanError >
Definition client.hpp:315
auto send_copy(const RequestPayload &payload) const -> bb::Expected< PendingResponse< Service, RequestPayload, RequestUserHeader, ResponsePayload, ResponseUserHeader >, RequestSendError >
Definition client.hpp:261
auto name() const -> PortNameView
Returns the [PortNameView] of the [Client].
Definition client.hpp:176
auto operator=(Client &&rhs) noexcept -> Client &
Definition client.hpp:139
auto id() const -> UniqueClientId
Returns the [UniqueClientId] of the [Client].
Definition client.hpp:164
auto max_active_requests() const -> uint64_t
Returns the maximal active requests a [Client] can send.
Definition client.hpp:199
~Client() noexcept
Definition client.hpp:155
auto initial_max_slice_len() const -> uint64_t
Returns the maximum number of elements that can be loaned in a slice.
Definition client.hpp:211
Non-owning view of a [PortName].
Definition port_name.hpp:25
static auto from_native_ptr(iox2_port_name_ptr m_ptr) -> PortNameView
Creates a [PortNameView] from a native [iox2_port_name_ptr].
Request header used by [MessagingPattern::RequestResponse].
Response 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
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 >
RequestSendError
Failure that can be emitted when a [RequestMut] is sent.
static void placement_default(S &payload)
Definition helper.hpp:22