Skip to content

Commit 5b8e6ee

Browse files
authored
Merge pull request #509 from elfenpiff/iox2-507-waitset-adjustments
[#507] waitset adjustments
2 parents 810fb87 + 71c4db4 commit 5b8e6ee

14 files changed

Lines changed: 353 additions & 191 deletions

File tree

examples/c/event_multiplexing/src/wait.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ struct CallbackContext {
2727

2828

2929
// the function that is called when a listener has received an event
30-
void on_event(iox2_waitset_attachment_id_h attachment_id, void* context) {
30+
iox2_callback_progression_e on_event(iox2_waitset_attachment_id_h attachment_id, void* context) {
3131
struct CallbackContext* ctx = (struct CallbackContext*) context;
3232

3333
iox2_event_id_t event_id;
@@ -65,6 +65,7 @@ void on_event(iox2_waitset_attachment_id_h attachment_id, void* context) {
6565
}
6666

6767
iox2_waitset_attachment_id_drop(attachment_id);
68+
return iox2_callback_progression_e_CONTINUE;
6869
}
6970

7071
//NOLINTBEGIN(readability-function-size)

examples/cxx/event_multiplexing/src/wait.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ auto main(int argc, char** argv) -> int {
8686
listener.try_wait_all([](auto event_id) { std::cout << " " << event_id; }).expect("");
8787
std::cout << std::endl;
8888
}
89+
90+
return iox2::CallbackProgression::Continue;
8991
};
9092

9193
std::cout << "Waiting on the following services: " << service_name_1.to_string().c_str() << ", "

examples/rust/event_multiplexing/wait.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
6969

7070
println!("");
7171
}
72+
73+
CallbackProgression::Continue
7274
};
7375

7476
// loops until the user has pressed CTRL+c, the application has received a SIGTERM or SIGINT

iceoryx2-bb/posix/src/deadline_queue.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,17 @@
3030
//! // contains all the deadlines where the deadline was hit
3131
//! let mut missed_deadlines = vec![];
3232
//! deadline_queue
33-
//! .missed_deadlines(|deadline_queue_index| missed_deadlines.push(deadline_queue_index));
33+
//! .missed_deadlines(|deadline_queue_index| {
34+
//! missed_deadlines.push(deadline_queue_index);
35+
//! CallbackProgression::Continue
36+
//! });
3437
//! ```
3538
36-
use std::{cell::RefCell, fmt::Debug, sync::atomic::Ordering, time::Duration};
39+
pub use iceoryx2_bb_elementary::CallbackProgression;
3740

38-
use iceoryx2_bb_elementary::CallbackProgression;
3941
use iceoryx2_bb_log::fail;
4042
use iceoryx2_pal_concurrency_sync::iox_atomic::IoxAtomicU64;
43+
use std::{cell::RefCell, fmt::Debug, sync::atomic::Ordering, time::Duration};
4144

4245
use crate::{
4346
clock::ClockType,
@@ -268,18 +271,15 @@ impl DeadlineQueue {
268271

269272
/// Iterates over all missed deadlines and calls the provided callback for each of them
270273
/// and provide the [`DeadlineQueueIndex`] to identify them.
271-
pub fn missed_deadlines<F: FnMut(DeadlineQueueIndex)>(
274+
pub fn missed_deadlines<F: FnMut(DeadlineQueueIndex) -> CallbackProgression>(
272275
&self,
273276
mut call: F,
274277
) -> Result<(), TimeError> {
275278
let now = fail!(from self, when Time::now_with_clock(self.clock_type),
276279
"Unable to return next duration since the current time could not be acquired.");
277280

278281
let now = now.as_duration().as_nanos();
279-
self.handle_missed_deadlines(now, |idx| {
280-
call(idx);
281-
CallbackProgression::Continue
282-
});
282+
self.handle_missed_deadlines(now, |idx| -> CallbackProgression { call(idx) });
283283

284284
Ok(())
285285
}

iceoryx2-bb/posix/tests/deadline_queue_tests.rs

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
// SPDX-License-Identifier: Apache-2.0 OR MIT
1212

1313
mod deadline_queue {
14+
use iceoryx2_bb_elementary::CallbackProgression;
1415
use iceoryx2_bb_posix::deadline_queue::*;
1516
use iceoryx2_bb_testing::assert_that;
1617
use std::time::Duration;
@@ -85,8 +86,11 @@ mod deadline_queue {
8586
.unwrap();
8687

8788
let mut missed_deadline_queues = vec![];
88-
sut.missed_deadlines(|idx| missed_deadline_queues.push(idx))
89-
.unwrap();
89+
sut.missed_deadlines(|idx| {
90+
missed_deadline_queues.push(idx);
91+
CallbackProgression::Continue
92+
})
93+
.unwrap();
9094

9195
assert_that!(missed_deadline_queues, len 0);
9296
}
@@ -104,8 +108,11 @@ mod deadline_queue {
104108
std::thread::sleep(Duration::from_millis(10));
105109

106110
let mut missed_deadlines = vec![];
107-
sut.missed_deadlines(|idx| missed_deadlines.push(idx))
108-
.unwrap();
111+
sut.missed_deadlines(|idx| {
112+
missed_deadlines.push(idx);
113+
CallbackProgression::Continue
114+
})
115+
.unwrap();
109116

110117
assert_that!(missed_deadlines, len 1);
111118
assert_that!(missed_deadlines, contains _guard_1.index());
@@ -122,15 +129,38 @@ mod deadline_queue {
122129
std::thread::sleep(Duration::from_millis(10));
123130

124131
let mut missed_deadlines = vec![];
125-
sut.missed_deadlines(|idx| missed_deadlines.push(idx))
126-
.unwrap();
132+
sut.missed_deadlines(|idx| {
133+
missed_deadlines.push(idx);
134+
CallbackProgression::Continue
135+
})
136+
.unwrap();
127137

128138
assert_that!(missed_deadlines, len 3);
129139
assert_that!(missed_deadlines, contains guard_1.index());
130140
assert_that!(missed_deadlines, contains guard_2.index());
131141
assert_that!(missed_deadlines, contains guard_3.index());
132142
}
133143

144+
#[test]
145+
fn missed_deadline_iteration_stops_when_requested() {
146+
let sut = DeadlineQueueBuilder::new().create().unwrap();
147+
148+
let _guard_1 = sut.add_deadline_interval(Duration::from_nanos(1)).unwrap();
149+
let _guard_2 = sut.add_deadline_interval(Duration::from_nanos(10)).unwrap();
150+
let _guard_3 = sut.add_deadline_interval(Duration::from_nanos(20)).unwrap();
151+
152+
std::thread::sleep(Duration::from_millis(10));
153+
154+
let mut missed_deadlines = vec![];
155+
sut.missed_deadlines(|idx| {
156+
missed_deadlines.push(idx);
157+
CallbackProgression::Stop
158+
})
159+
.unwrap();
160+
161+
assert_that!(missed_deadlines, len 1);
162+
}
163+
134164
#[test]
135165
fn duration_until_next_deadline_is_zero_if_deadline_is_already_missed() {
136166
let sut = DeadlineQueueBuilder::new().create().unwrap();
@@ -149,7 +179,8 @@ mod deadline_queue {
149179
let mut deadline_idx = None;
150180
sut.missed_deadlines(|idx| {
151181
missed_deadline_counter += 1;
152-
deadline_idx = Some(idx)
182+
deadline_idx = Some(idx);
183+
CallbackProgression::Continue
153184
})
154185
.unwrap();
155186

iceoryx2-ffi/cxx/include/iox2/enum_translation.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,8 @@ constexpr auto from<int, iox2::WaitSetRunResult>(const int value) noexcept -> io
704704
return iox2::WaitSetRunResult::TerminationRequest;
705705
case iox2_waitset_run_result_e_STOP_REQUEST:
706706
return iox2::WaitSetRunResult::StopRequest;
707+
case iox2_waitset_run_result_e_ALL_EVENTS_HANDLED:
708+
return iox2::WaitSetRunResult::AllEventsHandled;
707709
}
708710

709711
IOX_UNREACHABLE();

iceoryx2-ffi/cxx/include/iox2/waitset.hpp

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "iox/duration.hpp"
1717
#include "iox/expected.hpp"
18+
#include "iox2/callback_progression.hpp"
1819
#include "iox2/file_descriptor.hpp"
1920
#include "iox2/internal/iceoryx2.hpp"
2021
#include "iox2/listener.hpp"
@@ -78,7 +79,7 @@ class WaitSetAttachmentId {
7879
private:
7980
explicit WaitSetAttachmentId(iox2_waitset_attachment_id_h handle);
8081
template <ServiceType>
81-
friend auto run_callback(iox2_waitset_attachment_id_h, void*);
82+
friend auto run_callback(iox2_waitset_attachment_id_h, void*) -> iox2_callback_progression_e;
8283
template <ServiceType ST>
8384
friend auto operator==(const WaitSetAttachmentId<ST>&, const WaitSetAttachmentId<ST>&) -> bool;
8485
template <ServiceType ST>
@@ -103,7 +104,8 @@ auto operator<<(std::ostream& stream, const WaitSetAttachmentId<S>& self) -> std
103104
/// The [`WaitSet`] implements a reactor pattern and allows to wait on multiple events in one
104105
/// single call [`WaitSet::try_wait_and_process()`] until it wakes up or to run repeatedly with
105106
/// [`WaitSet::wait_and_process()`] until the a interrupt or termination signal was received or the user
106-
/// has explicitly requested to stop with [`WaitSet::stop()`].
107+
/// has explicitly requested to stop by returning [`CallbackProgression::Stop`] in the provided
108+
/// callback.
107109
///
108110
/// The [`Listener`] can be attached as well as sockets or anything else that
109111
/// can be packed into a [`FileDescriptorView`].
@@ -118,24 +120,39 @@ class WaitSet {
118120
auto operator=(WaitSet&&) noexcept -> WaitSet&;
119121
~WaitSet();
120122

121-
/// Can be called from within a callback during [`WaitSet::wait_and_process()`] to signal the [`WaitSet`]
122-
/// to stop running after this iteration.
123-
void stop();
124-
125-
/// Waits in an infinite loop on the [`WaitSet`]. The provided callback is called for every
126-
/// attachment that was triggered and the [`WaitSetAttachmentId`] is provided as an input argument to
127-
/// acquire the source.
123+
/// Waits until an event arrives on the [`WaitSet`], then collects all events by calling the
124+
/// provided `fn_call` callback with the corresponding [`WaitSetAttachmentId`]. In contrast
125+
/// to [`WaitSet::wait_and_process_once()`] it will never return until the user explicitly
126+
/// requests it by returning [`CallbackProgression::Stop`] or by receiving a signal.
127+
///
128+
/// The provided callback must return [`CallbackProgression::Continue`] to continue the event
129+
/// processing and handle the next event or [`CallbackProgression::Stop`] to return from this
130+
/// call immediately. All unhandled events will be lost forever and the call will return
131+
/// [`WaitSetRunResult::StopRequest`].
132+
///
128133
/// If an interrupt- (`SIGINT`) or a termination-signal (`SIGTERM`) was received, it will exit
129-
/// the loop and inform the user via [`WaitSetRunResult`].
130-
auto wait_and_process(const iox::function<void(WaitSetAttachmentId<S>)>& fn_call)
134+
/// the loop and inform the user with [`WaitSetRunResult::Interrupt`] or
135+
/// [`WaitSetRunResult::TerminationRequest`].
136+
auto wait_and_process(const iox::function<CallbackProgression(WaitSetAttachmentId<S>)>& fn_call)
131137
-> iox::expected<WaitSetRunResult, WaitSetRunError>;
132138

133-
/// Tries to wait on the [`WaitSet`]. The provided callback is called for every attachment that
134-
/// was triggered and the [`WaitSetAttachmentId`] is provided as an input argument to acquire the
135-
/// source.
136-
/// If nothing was triggered the [`WaitSet`] returns immediately.
137-
auto try_wait_and_process(const iox::function<void(WaitSetAttachmentId<S>)>& fn_call)
138-
-> iox::expected<void, WaitSetRunError>;
139+
/// Waits until an event arrives on the [`WaitSet`], then collects all events by calling the
140+
/// provided `fn_call` callback with the corresponding [`WaitSetAttachmentId`] and then
141+
/// returns. This makes it ideal to be called in some kind of event-loop.
142+
///
143+
/// The provided callback must return [`CallbackProgression::Continue`] to continue the event
144+
/// processing and handle the next event or [`CallbackProgression::Stop`] to return from this
145+
/// call immediately. All unhandled events will be lost forever and the call will return
146+
/// [`WaitSetRunResult::StopRequest`].
147+
///
148+
/// If an interrupt- (`SIGINT`) or a termination-signal (`SIGTERM`) was received, it will exit
149+
/// the loop and inform the user with [`WaitSetRunResult::Interrupt`] or
150+
/// [`WaitSetRunResult::TerminationRequest`].
151+
///
152+
/// When no signal was received and all events were handled, it will return
153+
/// [`WaitSetRunResult::AllEventsHandled`].
154+
auto wait_and_process_once(const iox::function<CallbackProgression(WaitSetAttachmentId<S>)>& fn_call)
155+
-> iox::expected<WaitSetRunResult, WaitSetRunError>;
139156

140157
/// Returns the capacity of the [`WaitSet`]
141158
auto capacity() const -> uint64_t;

iceoryx2-ffi/cxx/include/iox2/waitset_enums.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@ enum class WaitSetRunResult : uint8_t {
2828
TerminationRequest,
2929
/// An interrupt signal `SIGINT` was received.
3030
Interrupt,
31-
/// The user explicitly called [`WaitSet::stop()`].
32-
StopRequest
31+
/// The users callback returned [`CallbackProgression::Stop`].
32+
StopRequest,
33+
/// All events were handled.
34+
AllEventsHandled
3335
};
3436

3537
/// Defines the failures that can occur when attaching something with

iceoryx2-ffi/cxx/src/waitset.cpp

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -222,11 +222,6 @@ auto WaitSet<S>::is_empty() const -> bool {
222222
return iox2_waitset_is_empty(&m_handle);
223223
}
224224

225-
template <ServiceType S>
226-
void WaitSet<S>::stop() {
227-
iox2_waitset_stop(&m_handle);
228-
}
229-
230225
template <ServiceType S>
231226
auto WaitSet<S>::attach_interval(const iox::units::Duration deadline)
232227
-> iox::expected<WaitSetGuard<S>, WaitSetAttachmentError> {
@@ -290,13 +285,13 @@ auto WaitSet<S>::attach_notification(const Listener<S>& listener)
290285
}
291286

292287
template <ServiceType S>
293-
auto run_callback(iox2_waitset_attachment_id_h attachment_id, void* context) {
294-
auto* fn_call = internal::ctx_cast<iox::function<void(WaitSetAttachmentId<S>)>>(context);
295-
fn_call->value()(WaitSetAttachmentId<S>(attachment_id));
288+
auto run_callback(iox2_waitset_attachment_id_h attachment_id, void* context) -> iox2_callback_progression_e {
289+
auto* fn_call = internal::ctx_cast<iox::function<CallbackProgression(WaitSetAttachmentId<S>)>>(context);
290+
return iox::into<iox2_callback_progression_e>(fn_call->value()(WaitSetAttachmentId<S>(attachment_id)));
296291
}
297292

298293
template <ServiceType S>
299-
auto WaitSet<S>::wait_and_process(const iox::function<void(WaitSetAttachmentId<S>)>& fn_call)
294+
auto WaitSet<S>::wait_and_process(const iox::function<CallbackProgression(WaitSetAttachmentId<S>)>& fn_call)
300295
-> iox::expected<WaitSetRunResult, WaitSetRunError> {
301296
iox2_waitset_run_result_e run_result = iox2_waitset_run_result_e_STOP_REQUEST;
302297
auto ctx = internal::ctx(fn_call);
@@ -310,13 +305,14 @@ auto WaitSet<S>::wait_and_process(const iox::function<void(WaitSetAttachmentId<S
310305
}
311306

312307
template <ServiceType S>
313-
auto WaitSet<S>::try_wait_and_process(const iox::function<void(WaitSetAttachmentId<S>)>& fn_call)
314-
-> iox::expected<void, WaitSetRunError> {
308+
auto WaitSet<S>::wait_and_process_once(const iox::function<CallbackProgression(WaitSetAttachmentId<S>)>& fn_call)
309+
-> iox::expected<WaitSetRunResult, WaitSetRunError> {
310+
iox2_waitset_run_result_e run_result = iox2_waitset_run_result_e_STOP_REQUEST;
315311
auto ctx = internal::ctx(fn_call);
316-
auto result = iox2_waitset_try_wait_and_process(&m_handle, run_callback<S>, static_cast<void*>(&ctx));
312+
auto result = iox2_waitset_wait_and_process_once(&m_handle, run_callback<S>, static_cast<void*>(&ctx), &run_result);
317313

318314
if (result == IOX2_OK) {
319-
return iox::ok();
315+
return iox::ok(iox::into<WaitSetRunResult>(static_cast<int>(run_result)));
320316
}
321317

322318
return iox::err(iox::into<WaitSetRunError>(result));

0 commit comments

Comments
 (0)