Skip to content

Commit

Permalink
Merge pull request #2252 from elBoberido/iox-2251-fix-listener-examples
Browse files Browse the repository at this point in the history
iox-#2251 Fix 'Listener' examples
  • Loading branch information
elBoberido committed Apr 15, 2024
2 parents 79e6bce + bc98a7f commit 0cf06f2
Show file tree
Hide file tree
Showing 12 changed files with 48 additions and 20 deletions.
2 changes: 1 addition & 1 deletion doc/aspice_swe3_4/swe_docu_guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ In iceoryx are also custom tags used for extended documentation like errors.

### Include Additional Header Into Documentation

In some cases, the implementation of a component is is placed in an internal folder and the header in the public folder acts as a trampoline with some using declarations.
In some cases, the implementation of a component is placed in an internal folder, and the header in the public folder acts as a trampoline, with some using declarations.
The iceoryx endpoints like `Publisher`, `Subscriber`, etc. are such examples where the public header only includes a using declaration to the actual implementation.
In order to include the documentation of these components, the header containing the documentation can be added to the `INCLUDE_DIR_AND_ADDITIONAL_FILES` list in the CMakeLists.txt.

Expand Down
10 changes: 10 additions & 0 deletions doc/website/FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ A possible alternative is
* If 256 is not enough, increase the maximum value `IOX_MAX_CHUNKS_HELD_PER_SUBSCRIBER_SIMULTANEOUSLY`
via [the CMake switch](advanced/configuration-guide.md)

## Missing samples with a Listener

In case the subscriber is used in combination with a listener, some samples might just wait in receiver queue to be taken.
The `Listener` uses events, which are faster than states of the `WaitSet` but this also means that if the publisher e.g.
fires 5 events while the subscriber is executing the `onSampleReceivedCallback` it will be triggered only once after it
leaves the callback. If you do not take care of taking all the data out of the queue, they will just stay there and fill
up the queue. The default queue size is 256 samples. This means the samples need to be taken out in a loop in the
`onSampleReceivedCallback` until `take` reports an empty queue. Alternatively the `WaitSet` can be used instead of the `Listener`.
The `WaitSet` supports states as well as events and if used with states it will fire as long as there are data in the queue.

## Solving the error `MEPOO__MEMPOOL_GETCHUNK_POOL_IS_RUNNING_OUT_OF_CHUNKS`

Possible solutions are one of the following:
Expand Down
1 change: 1 addition & 0 deletions doc/website/release-notes/iceoryx-unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@
- Fix `const` value assignment in `iox::optional` [\#2224](https://github.com/eclipse-iceoryx/iceoryx/issues/2224)
- Generated files cause recompilation even without any changes [#2210](https://github.com/eclipse-iceoryx/iceoryx/issues/2210)
- Fix span_iterator constructor to prevent assertion when iterating over spans [#2216](https://github.com/eclipse-iceoryx/iceoryx/issues/2216)
- Listener examples need to take all samples in the callback [#2251](https://github.com/eclipse-iceoryx/iceoryx/issues/2251)

**Refactoring:**

Expand Down
18 changes: 12 additions & 6 deletions iceoryx_examples/callbacks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,16 +165,17 @@ void heartbeatCallback(iox::popo::UserTrigger*)
}
```
The `onSampleReceivedCallback` is more complex. We first acquire the received
sample and check which subscriber signaled the event by acquiring the subscriber's
The `onSampleReceivedCallback` is more complex. We first acquire all the received
samples and check which subscriber signaled the event by acquiring the subscriber's
service description. If the instance is equal to `FrontLeft` we store the sample
in the `leftCache` otherwise in the `rightCache`.
<!--[geoffrey][iceoryx_examples/callbacks/ice_callbacks_subscriber.cpp][[subscriber callback][get data]]-->
```cpp
void onSampleReceivedCallback(iox::popo::Subscriber<CounterTopic>* subscriber)
{
subscriber->take().and_then([subscriber](auto& sample) {
// take all samples from the subscriber queue
while (subscriber->take().and_then([subscriber](auto& sample) {
auto instanceString = subscriber->getServiceDescription().getInstanceIDString();
// store the sample in the corresponding cache
Expand All @@ -188,7 +189,9 @@ void onSampleReceivedCallback(iox::popo::Subscriber<CounterTopic>* subscriber)
}
std::cout << "received: " << sample->counter << std::endl;
});
}))
{
}
// ...
}
```
Expand Down Expand Up @@ -304,7 +307,8 @@ argument, the pointer to the object itself, called `self`.
```cpp
static void onSampleReceivedCallback(iox::popo::Subscriber<CounterTopic>* subscriber, CounterService* self)
{
subscriber->take().and_then([subscriber, self](auto& sample) {
// take all samples from the subscriber queue
while (subscriber->take().and_then([subscriber, self](auto& sample) {
auto instanceString = subscriber->getServiceDescription().getInstanceIDString();
// store the sample in the corresponding cache
Expand All @@ -318,7 +322,9 @@ static void onSampleReceivedCallback(iox::popo::Subscriber<CounterTopic>* subscr
}
std::cout << "received: " << sample->counter << std::endl;
});
}))
{
}
// if both caches are filled we can process them
if (self->m_leftCache && self->m_rightCache)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ class CounterService
//! [callback]
static void onSampleReceivedCallback(iox::popo::Subscriber<CounterTopic>* subscriber, CounterService* self)
{
subscriber->take().and_then([subscriber, self](auto& sample) {
// take all samples from the subscriber queue
while (subscriber->take().and_then([subscriber, self](auto& sample) {
auto instanceString = subscriber->getServiceDescription().getInstanceIDString();

// store the sample in the corresponding cache
Expand All @@ -82,7 +83,9 @@ class CounterService
}

std::cout << "received: " << sample->counter << std::endl;
});
}))
{
}

// if both caches are filled we can process them
if (self->m_leftCache && self->m_rightCache)
Expand Down
7 changes: 5 additions & 2 deletions iceoryx_examples/callbacks/ice_callbacks_subscriber.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ void heartbeatCallback(iox::popo::UserTrigger*)
void onSampleReceivedCallback(iox::popo::Subscriber<CounterTopic>* subscriber)
{
//! [get data]
subscriber->take().and_then([subscriber](auto& sample) {
// take all samples from the subscriber queue
while (subscriber->take().and_then([subscriber](auto& sample) {
auto instanceString = subscriber->getServiceDescription().getInstanceIDString();

// store the sample in the corresponding cache
Expand All @@ -56,7 +57,9 @@ void onSampleReceivedCallback(iox::popo::Subscriber<CounterTopic>* subscriber)
}

std::cout << "received: " << sample->counter << std::endl;
});
}))
{
}
//! [get data]

//! [process data]
Expand Down
7 changes: 4 additions & 3 deletions iceoryx_examples/callbacks_in_c/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,17 +158,18 @@ void heartbeatCallback(iox_user_trigger_t userTrigger)
}
```
The `onSampleReceivedCallback` is a little bit more complex. First we acquire
the chunk and then we have to find out which subscriber received the chunk. For that
The `onSampleReceivedCallback` is a little bit more complex. First we acquire all
the chunks and also have to find out which subscriber received the chunk. For that
we acquire the service description of the subscriber and if its instance equals
`FrontLeft` we store the chunk value in the `leftCache` otherwise in the `rightCache`.
<!--[geoffrey][iceoryx_examples/callbacks_in_c/ice_c_callbacks_subscriber.c][[subscriber callback][get data]]-->
```c
void onSampleReceivedCallback(iox_sub_t subscriber)
{
// take all samples from the subscriber queue
const struct CounterTopic* userPayload;
if (iox_sub_take_chunk(subscriber, (const void**)&userPayload) == ChunkReceiveResult_SUCCESS)
while (iox_sub_take_chunk(subscriber, (const void**)&userPayload) == ChunkReceiveResult_SUCCESS)
{
iox_service_description_t serviceDescription = iox_sub_get_service_description(subscriber);
if (strcmp(serviceDescription.instanceString, "FrontLeft") == 0)
Expand Down
3 changes: 2 additions & 1 deletion iceoryx_examples/callbacks_in_c/ice_c_callbacks_subscriber.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,9 @@ void* cyclicHeartbeatTrigger(void* dontCare)
void onSampleReceivedCallback(iox_sub_t subscriber)
{
//! [get data]
// take all samples from the subscriber queue
const struct CounterTopic* userPayload;
if (iox_sub_take_chunk(subscriber, (const void**)&userPayload) == ChunkReceiveResult_SUCCESS)
while (iox_sub_take_chunk(subscriber, (const void**)&userPayload) == ChunkReceiveResult_SUCCESS)
{
iox_service_description_t serviceDescription = iox_sub_get_service_description(subscriber);
if (strcmp(serviceDescription.instanceString, "FrontLeft") == 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ void onSampleReceivedCallback(iox_sub_t subscriber, void* contextData)

//! [get data]
const struct CounterTopic* userPayload;
if (iox_sub_take_chunk(subscriber, (const void**)&userPayload) == ChunkReceiveResult_SUCCESS)
// take all samples from the subscriber queue
while (iox_sub_take_chunk(subscriber, (const void**)&userPayload) == ChunkReceiveResult_SUCCESS)
{
iox_service_description_t serviceDescription = iox_sub_get_service_description(subscriber);
if (strcmp(serviceDescription.instanceString, "FrontLeft") == 0)
Expand Down
2 changes: 2 additions & 0 deletions iceoryx_examples/ice_access_control/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ Do the following to configure shared memory segments when building a custom RouD
<!--[geoffrey][iceoryx_examples/ice_access_control/roudi_main_static_segments.cpp][config]-->
```cpp
iox::IceoryxConfig config;
static_cast<iox::config::RouDiConfig&>(config) = cmdLineArgs.value().roudiConfig;


// Create Mempool Config
iox::mepoo::MePooConfig mepooConfig;
Expand Down
4 changes: 2 additions & 2 deletions iceoryx_examples/waitset/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -323,8 +323,8 @@ for (auto i = 0U; i < NUMBER_OF_SUBSCRIBERS; ++i)
subscriberVector.emplace_back(iox::capro::ServiceDescription{"Radar", "FrontLeft", "Counter"});
auto& subscriber = subscriberVector.back();

/// important: the user has to ensure that the contextData (sumOfAllSamples) lives as long as
/// the subscriber with its callback is attached to the listener
/// important: the user has to ensure that the 'contextData' (here 'sumOfAllSamples') lives as long as
/// the subscriber with its callback when attached to the 'waitset'
waitset
.attachEvent(subscriber,
iox::popo::SubscriberEvent::DATA_RECEIVED,
Expand Down
4 changes: 2 additions & 2 deletions iceoryx_examples/waitset/ice_waitset_gateway.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ int main()
subscriberVector.emplace_back(iox::capro::ServiceDescription{"Radar", "FrontLeft", "Counter"});
auto& subscriber = subscriberVector.back();

/// important: the user has to ensure that the contextData (sumOfAllSamples) lives as long as
/// the subscriber with its callback is attached to the listener
/// important: the user has to ensure that the 'contextData' (here 'sumOfAllSamples') lives as long as
/// the subscriber with its callback when attached to the 'waitset'
waitset
.attachEvent(subscriber,
iox::popo::SubscriberEvent::DATA_RECEIVED,
Expand Down

0 comments on commit 0cf06f2

Please sign in to comment.