Skip to content

Commit 5157bb1

Browse files
authored
Merge pull request #680 from elfenpiff/iox2-429-add-response-channel
[#429] add response channel
2 parents a586076 + a868ac3 commit 5157bb1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+4762
-790
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/README.md

+18-5
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,16 @@ Adjusting `global` settings ensures a non-interfering setup.
119119

120120
### Service: Request Response Messaging Pattern
121121

122+
* `defaults.request-response.client-unable-to-deliver-strategy` -
123+
[`Block`|`DiscardSample`]: Default strategy for non-overflowing setups
124+
when delivery fails.
125+
* `defaults.request-response.client-expired-connection-buffer` - [int]:
126+
Expired connection buffer size of the client. Connections to servers
127+
are expired when the server disconnected from the service and the
128+
connection contains unconsumed responses.
129+
* `defaults.request-response.enable-fire-and-forget-requests` -
130+
[`true`|`false`]: Enables the client to send requests without
131+
expecting a response.
122132
* `defaults.request-response.enable-safe-overflow-for-requests` -
123133
[`true`|`false`]: Defines if the request buffer of the service safely
124134
overflows.
@@ -130,14 +140,17 @@ Adjusting `global` settings ensures a non-interfering setup.
130140
* `defaults.request-response.max-borrowed-responses-per-pending-response` -
131141
[int]: The maximum number of borrowed responses a client can hold in
132142
parallel per pending response.
143+
* `defaults.request-response.max-clients` - [int]:
144+
The maximum amount of supported clients.
145+
* `defaults.request-response.max-nodes` - [int]:
146+
The maximum amount of supported nodes. Defines indirectly how many
147+
processes can open the service at the same time.
133148
* `defaults.request-response.max-response-buffer-size` - [int]:
134149
The maximum buffer size for responses for an active request.
135150
* `defaults.request-response.max-request-buffer-size` - [int]:
136151
The maximum buffer size for requests for a server.
137152
* `defaults.request-response.max-servers` - [int]:
138153
The maximum amount of supported servers.
139-
* `defaults.request-response.max-clients` - [int]:
140-
The maximum amount of supported clients.
141-
* `defaults.request-response.max-nodes` - [int]:
142-
The maximum amount of supported nodes. Defines indirectly how many
143-
processes can open the service at the same time.
154+
* `defaults.request-response.server-unable-to-deliver-strategy` -
155+
[`Block`|`DiscardSample`]: Default strategy for non-overflowing setups
156+
when delivery fails.

config/iceoryx2.toml

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ creation-timeout.secs = 0
2222
creation-timeout.nanos = 500000000
2323

2424
[defaults.request-response]
25+
client-expired-connection-buffer = 128
26+
client-unable-to-deliver-strategy = 'Block' # or 'DiscardSample'
27+
enable-fire-and-forget-requests = true
2528
enable-safe-overflow-for-requests = true
2629
enable-safe-overflow-for-responses = true
2730
max-active-requests-per-client = 4
@@ -30,9 +33,8 @@ max-servers = 2
3033
max-clients = 8
3134
max-nodes = 20
3235
max-borrowed-responses-per-pending-response = 2
33-
client-max-loaned-requests = 2
36+
max-loaned-requests = 2
3437
server-max-loaned-responses-per-request = 2
35-
client-unable-to-deliver-strategy = 'Block' # or 'DiscardSample'
3638
server-unable-to-deliver-strategy = 'Block' # or 'DiscardSample'
3739

3840
[defaults.publish-subscribe]

doc/release-notes/iceoryx2-unreleased.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
[#264](https://github.com/eclipse-iceoryx/iceoryx2/issues/264)
1616
* Read LogLevel from environment variable
1717
[#396](https://github.com/eclipse-iceoryx/iceoryx2/issues/396)
18+
* Add Request-Response messaging pattern
19+
[#429](https://github.com/eclipse-iceoryx/iceoryx2/issues/429)
1820
* Lookup config file in default locations
1921
[#442](https://github.com/eclipse-iceoryx/iceoryx2/issues/442)
2022
* Introduce `socket_pair` abstraction in POSIX wrapper
@@ -82,7 +84,6 @@
8284
* Remove the `print_system_configuration()` function in
8385
`iceoryx2-bb/posix/src/system_configuration.rs` file and move it into the CLI `iox2-config`
8486
[#432](https://github.com/eclipse-iceoryx/iceoryx2/issues/432)
85-
8687
* Remove obsolete POSIX wrapper
8788
[#594](https://github.com/eclipse-iceoryx/iceoryx2/issues/594)
8889
* Updated all dependencies and increased MSRV to 1.81

examples/rust/request_response/client.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,21 @@ fn main() -> Result<(), Box<dyn core::error::Error>> {
2929

3030
let mut counter: u64 = 0;
3131

32+
// sending first request by using slower, inefficient copy API
33+
println!("Send request {} ...", counter);
34+
let mut pending_response = client.send_copy(counter)?;
3235
while node.wait(CYCLE_TIME).is_ok() {
36+
// acquire all responses from our buffer
37+
while let Some(response) = pending_response.receive()? {
38+
println!(" received response: {:?}", *response);
39+
}
40+
3341
counter += 1;
42+
// send all other requests by using zero copy API
3443
let request = client.loan_uninit()?;
3544
let request = request.write_payload(counter);
3645

37-
let _pending_response = request.send()?;
46+
pending_response = request.send()?;
3847

3948
println!("Send request {} ...", counter);
4049
}

examples/rust/request_response/server.rs

+29-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use core::time::Duration;
1414
use examples_common::TransmissionData;
1515
use iceoryx2::prelude::*;
1616

17-
const CYCLE_TIME: Duration = Duration::from_millis(10);
17+
const CYCLE_TIME: Duration = Duration::from_millis(100);
1818

1919
fn main() -> Result<(), Box<dyn core::error::Error>> {
2020
set_log_level_from_env_or(LogLevel::Info);
@@ -27,10 +27,38 @@ fn main() -> Result<(), Box<dyn core::error::Error>> {
2727

2828
let server = service.server_builder().create()?;
2929

30+
let mut counter = 0;
3031
while node.wait(CYCLE_TIME).is_ok() {
3132
while let Some(active_request) = server.receive()? {
3233
println!("received request: {:?}", *active_request);
34+
35+
// send first response by using the slower, non-zero-copy
36+
// API
37+
active_request.send_copy(TransmissionData {
38+
x: 5 + counter,
39+
y: 6 * counter,
40+
funky: 7.77,
41+
})?;
42+
43+
// use zero copy API, send out some samples to utilize
44+
// the streaming API
45+
for n in 0..*active_request % 2 {
46+
let sample = active_request.loan_uninit()?;
47+
let sample = sample.write_payload(TransmissionData {
48+
x: counter as i32 * (n as i32 + 1),
49+
y: counter as i32 + n as i32,
50+
funky: counter as f64 * 0.1234,
51+
});
52+
sample.send()?;
53+
}
54+
55+
// when active_request is dropped it marks the connection so
56+
// that the corresponding pending response sees that no more
57+
// responses are arriving
58+
drop(active_request);
3359
}
60+
61+
counter += 1;
3462
}
3563

3664
println!("exit");

iceoryx2-bb/container/src/vec.rs

+42-1
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,17 @@ pub mod details {
294294
true
295295
}
296296

297+
unsafe fn remove_impl(&mut self, index: usize) -> T {
298+
self.verify_init("remove()");
299+
debug_assert!(index < self.len());
300+
301+
let ptr = self.as_mut_ptr().add(index);
302+
let value = core::ptr::read(ptr);
303+
core::ptr::copy(ptr.add(1), ptr, self.len - index - 1);
304+
self.len -= 1;
305+
value
306+
}
307+
297308
unsafe fn pop_impl(&mut self) -> Option<T> {
298309
if self.is_empty() {
299310
return None;
@@ -329,7 +340,7 @@ pub mod details {
329340
}
330341

331342
impl<T> MetaVec<T, GenericOwningPointer> {
332-
/// Creates a new [`Queue`] with the provided capacity
343+
/// Creates a new [`Vec`] with the provided capacity
333344
pub fn new(capacity: usize) -> Self {
334345
Self {
335346
data_ptr: OwningPointer::<MaybeUninit<T>>::new_with_alloc(capacity),
@@ -340,6 +351,16 @@ pub mod details {
340351
}
341352
}
342353

354+
/// Creates a new [`Vec`] with the provided capacity and fills it by
355+
/// using the provided callback
356+
pub fn from_fn<F: FnMut(usize) -> T>(capacity: usize, mut callback: F) -> Self {
357+
let mut new_self = Self::new(capacity);
358+
for n in 0..capacity {
359+
new_self.push(callback(n));
360+
}
361+
new_self
362+
}
363+
343364
/// Adds an element at the end of the vector. If the vector is full and the element cannot be
344365
/// added it returns false, otherwise true.
345366
pub fn push(&mut self, value: T) -> bool {
@@ -373,6 +394,11 @@ pub mod details {
373394
unsafe { self.pop_impl() }
374395
}
375396

397+
/// Removes the element at the provided index and returns it.
398+
pub fn remove(&mut self, index: usize) -> T {
399+
unsafe { self.remove_impl(index) }
400+
}
401+
376402
/// Removes all elements from the vector
377403
pub fn clear(&mut self) {
378404
unsafe { self.clear_impl() }
@@ -455,6 +481,16 @@ pub mod details {
455481
self.pop_impl()
456482
}
457483

484+
/// Removes the element at the provided index and returns it.
485+
///
486+
/// # Safety
487+
///
488+
/// * [`RelocatableVec::init()`] must be called once before
489+
///
490+
pub unsafe fn remove(&mut self, index: usize) -> T {
491+
unsafe { self.remove_impl(index) }
492+
}
493+
458494
/// Removes all elements from the vector
459495
///
460496
/// # Safety
@@ -681,6 +717,11 @@ impl<T, const CAPACITY: usize> FixedSizeVec<T, CAPACITY> {
681717
unsafe { self.state.pop() }
682718
}
683719

720+
/// Removes the element at the provided index and returns it.
721+
pub fn remove(&mut self, index: usize) -> T {
722+
unsafe { self.state.remove(index) }
723+
}
724+
684725
/// Removes all elements from the vector
685726
pub fn clear(&mut self) {
686727
unsafe { self.state.clear() }

iceoryx2-bb/container/tests/vec_tests.rs

+36
Original file line numberDiff line numberDiff line change
@@ -333,4 +333,40 @@ mod vec {
333333
assert_that!(sut.pop(), eq Some(TEST_VALUE));
334334
assert_that!(sut, len 0);
335335
}
336+
337+
#[test]
338+
fn remove_reverse_order_works() {
339+
const CAPACITY: usize = 12;
340+
let mut sut = Vec::<usize>::new(CAPACITY);
341+
342+
for n in 0..CAPACITY {
343+
sut.push(n);
344+
}
345+
346+
for n in (0..CAPACITY).rev() {
347+
assert_that!(sut.remove(n), eq n);
348+
349+
for (idx, v) in sut.iter().enumerate() {
350+
assert_that!(*v, eq idx);
351+
}
352+
}
353+
}
354+
355+
#[test]
356+
fn remove_works() {
357+
const CAPACITY: usize = 12;
358+
let mut sut = Vec::<usize>::new(CAPACITY);
359+
360+
for n in 0..CAPACITY {
361+
sut.push(n);
362+
}
363+
364+
for n in 0..CAPACITY {
365+
assert_that!(sut.remove(0), eq n);
366+
367+
for (idx, v) in sut.iter().enumerate() {
368+
assert_that!(*v, eq idx + n + 1);
369+
}
370+
}
371+
}
336372
}

iceoryx2-bb/posix/src/memory_lock.rs

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub enum MemoryLockCreationError {
3030
UnknownError(i32),
3131
}
3232

33+
#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
3334
pub enum MemoryLockAllError {
3435
UnableToLock,
3536
WouldExceedMainMemory,

iceoryx2-bb/testing/src/assert.rs

+11
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,17 @@ macro_rules! assert_that {
7272
}
7373
}
7474
};
75+
($lhs:expr, aligned_to $rhs:expr) => {
76+
{
77+
let lval = $lhs as usize;
78+
let rval = $rhs as usize;
79+
let act_result = lval % rval;
80+
81+
if !(act_result == 0) {
82+
assert_that!(message $lhs, $rhs, lval, rval, "aligned to");
83+
}
84+
}
85+
};
7586
($lhs:expr, mod $rhs:expr, is $result:expr) => {
7687
{
7788
let lval = &$lhs;

iceoryx2-cal/BUILD.bazel

+3
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ rust_library(
4444
"@crate_index//:tiny-fn",
4545
"@crate_index//:toml",
4646
],
47+
proc_macro_deps = [
48+
"//iceoryx2-bb/derive-macros:iceoryx2-bb-derive-macros",
49+
],
4750
)
4851

4952
rust_test_suite(

iceoryx2-cal/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ dev_permissions = []
1919
[dependencies]
2020
iceoryx2-bb-posix = { workspace = true }
2121
iceoryx2-bb-container = { workspace = true }
22+
iceoryx2-bb-derive-macros = { workspace = true }
2223
iceoryx2-bb-system-types = { workspace = true }
2324
iceoryx2-bb-log = { workspace = true }
2425
iceoryx2-bb-elementary = { workspace = true }

iceoryx2-cal/src/dynamic_storage/mod.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,12 @@ enum_gen! {
106106
pub trait DynamicStorageBuilder<'builder, T: Send + Sync, D: DynamicStorage<T>>:
107107
Debug + Sized + NamedConceptBuilder<D>
108108
{
109-
/// Defines if a newly created [`DynamicStorage`] owns the underlying resources
109+
/// Defines if `T::Drop` shall be called when the [`DynamicStorage`] is removed. The default
110+
/// is [`true`].
111+
fn call_drop_on_destruction(self, value: bool) -> Self;
112+
113+
/// Defines if a newly created [`DynamicStorage`] owns the underlying resources. The default
114+
/// is [`true`].
110115
fn has_ownership(self, value: bool) -> Self;
111116

112117
/// Sets the size of the supplementary data. Only relevant when it is newly created otherwise

0 commit comments

Comments
 (0)