Skip to content

Commit

Permalink
Merge pull request #460 from ApexAI/iox-#337-create-PeriodicTask
Browse files Browse the repository at this point in the history
Iox #337 create periodic task
  • Loading branch information
elBoberido committed Dec 22, 2020
2 parents 56e2f18 + 1d37360 commit 0186384
Show file tree
Hide file tree
Showing 26 changed files with 425 additions and 101 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -2,6 +2,7 @@ build/
build_out_of_tree/
install/
/CMakeLists.txt
clangd/
.vscode
/**/*.user
iceoryx_utils/doc/html/
Expand Down
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Expand Up @@ -149,13 +149,13 @@ The coverage scan applies to Quality level 3 and partly level 2 with branch cove
For having a coverage report iceoryx needs to be compiled with coverage flags and the tests needs to be executed.
You can do this with one command in iceroyx folder like this:
```
./tools/iceoryx_build_test.sh clean buildall -c <testlevel>
./tools/iceoryx_build_test.sh clean build-all -c <testlevel>
```
Optionally you can use buildall option to get coverage for extensions like DDS or C-Binding.
Optionally you can use build-all option to get coverage for extensions like DDS or C-Binding.
The -c flag indicates that you want to have a coverage report and you can pass there the needed testlevel. Per default the testlevel is set to 'all'.
example:
```
./tools/iceoryx_build_test.sh buildall clean -c unit
./tools/iceoryx_build_test.sh build-all clean -c unit
```
For having only reports for unit-test. In the script tools/gcov/lcov_generate.sh is the initial scan, filtering and report generation automatically done.

Expand Down
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -54,11 +54,11 @@ An example for such a "porcelain" API would be [ROS2](https://www.ros.org/). Oth

## Build and install

You can find the build and installation guidelines [here](doc/installation-guide.md).
You can find the build and installation guidelines [here](doc/website/getting-started/installation.md).

## Examples

After you've built all the necessary things, you can continue playing around with the [examples](./iceoryx_examples).
After you've built all the necessary things, you can continue playing around with the [examples](./iceoryx_examples/README.md).

## Build and run in a Docker environment

Expand Down
2 changes: 1 addition & 1 deletion doc/website/getting-started/installation.md
Expand Up @@ -104,7 +104,7 @@ The script currently only works for Linux and QNX, it is planned to offer a mult
2. Build everything
```
cd iceoryx
./tools/iceoryx_build_test.sh build_all
./tools/iceoryx_build_test.sh build-all
```

You can use the help for getting an overview over the available options:
Expand Down
59 changes: 24 additions & 35 deletions iceoryx_examples/icedelivery/README.md
Expand Up @@ -2,12 +2,12 @@

## Introduction

This example showcases a one-way data transmission setup with zero-copy inter-process communication (IPC) on iceoryx.
It provides publisher and subscriber applications. They come in two API flavours (untyped and typed).
This example showcases a data transmission setup with zero-copy inter-process communication (IPC) on iceoryx.
It provides publisher and subscriber applications. They come in two C++ API flavours (untyped and typed). Check icedelivery_on_c for the C API

## Run icedelivery

Create three terminals and run one command in each of them. Choose one publisher and one subscriber and mix the typed and untyped versions.
Create different terminals and run one command in each of them. Choose at least one publisher and one subscriber for having a data communication. You can also mix the typed and untyped versions. And if you feel like crazy today you start several publishers and subscribers from icedelivery and icedelivery_on_c (needs the default n:m communication, not possible if you build with the ONE_TO_MANY option)
```sh
# If installed and available in PATH environment variable
iox-roudi
Expand Down Expand Up @@ -46,31 +46,27 @@ RouDi is ready for clients
```
2020-12-20 16:05:01.837 [ Debug ]: Application registered management segment 0x7fd6d39e3000 with size 64244064 to id 1
2020-12-20 16:26:42.791 [ Info ]: Application registered payload segment 0x7f377c4e6000 with size 149134400 to id 2
Sent {five,two} times value: (1, 1, 1)
Sent {five,two} times value: (2, 2, 2)
Sent {five,two} times value: (3, 3, 3)
Sent {five,two} times value: 1
Sent {five,two} times value: 2
Sent {five,two} times value: 3
```

### Subscriber application (typed)
```
2020-12-20 16:26:58.839 [ Debug ] Application registered management segment 0x7f6353c04000 with size 64244064 to id 1
2020-12-20 16:26:58.839 [ Info ] Application registered payload segment 0x7f634ab8c000 with size 149134400 to id 2
Not subscribed!
Got value: (2, 2, 2)
Got value: (2, 2, 2)
Got value: (2, 2, 2)
Got value: (2, 2, 2)
Got value: (2, 2, 2)
Didn't get a value, but do something anyway.
Didn't get a value, but do something anyway.
Didn't get a value, but do something anyway.
Didn't get a value, but do something anyway.
Didn't get a value, but do something anyway.
Got value: (3, 3, 3)
Got value: (3, 3, 3)
Got value: (3, 3, 3)
Got value: (3, 3, 3)
Got value: (3, 3, 3)
Got value: 2
Got value: 2
Got value: 2
Got value: 2
Got value: 2
Got value: 3
Got value: 3
Got value: 3
Got value: 3
Got value: 3
```

Expand All @@ -79,18 +75,12 @@ Got value: (3, 3, 3)
2020-12-20 16:26:58.839 [ Debug ] Application registered management segment 0x7f6353c04000 with size 64244064 to id 1
2020-12-20 16:26:58.839 [ Info ] Application registered payload segment 0x7f634ab8c000 with size 149134400 to id 2
Not subscribed!
Got value: (2, 2, 2)
Got value: (2, 2, 2)
Didn't get a value, but do something anyway.
Didn't get a value, but do something anyway.
Didn't get a value, but do something anyway.
Didn't get a value, but do something anyway.
Didn't get a value, but do something anyway.
Didn't get a value, but do something anyway.
Didn't get a value, but do something anyway.
Didn't get a value, but do something anyway.
Got value: (3, 3, 3)
Got value: (3, 3, 3)
Got value: 2
Got value: 2
Got value: 3
Got value: 3
```

## Code walkthrough
Expand Down Expand Up @@ -293,8 +283,7 @@ need to take care about all cases, but it is advised to do so.
In the `and_then` case the content of the sample is printed to the command line:
```cpp
auto object = static_cast<const RadarObject*>(sample->get());
std::cout << "Got value: (" << object->x << ", " << object->y << ", " << object->z << ")"
<< std::endl;
std::cout << "Got value: " << object->x << std::endl;
```

Please note the `static_cast` before reading out the data. It is necessary, because the untyped subscriber is unaware
Expand Down
4 changes: 2 additions & 2 deletions iceoryx_examples/icedelivery/iox_publisher_typed.cpp
Expand Up @@ -42,7 +42,7 @@ int main()
iox::popo::TypedPublisher<RadarObject> typedPublisher({"Radar", "FrontLeft", "Object"});
typedPublisher.offer();

float_t ct = 0.0;
double ct = 0.0;
while (!killswitch)
{
++ct;
Expand Down Expand Up @@ -96,7 +96,7 @@ int main()
typedPublisher.publishResultOf(getRadarObject, ct);
typedPublisher.publishResultOf([&ct](RadarObject* object) { *object = RadarObject(ct, ct, ct); });

std::cout << "Sent five times value: (" << ct << ", " << ct << ", " << ct << ")" << std::endl;
std::cout << "Sent five times value: " << ct << std::endl;

std::this_thread::sleep_for(std::chrono::seconds(1));
}
Expand Down
4 changes: 2 additions & 2 deletions iceoryx_examples/icedelivery/iox_publisher_untyped.cpp
Expand Up @@ -37,7 +37,7 @@ int main()
iox::popo::UntypedPublisher untypedPublisher({"Radar", "FrontLeft", "Object"});
untypedPublisher.offer();

float_t ct = 0.0;
double ct = 0.0;
while (!killswitch)
{
++ct;
Expand Down Expand Up @@ -73,7 +73,7 @@ int main()
// Do something with error
});

std::cout << "Sent two times value: (" << ct << ", " << ct << ", " << ct << ")" << std::endl;
std::cout << "Sent two times value: " << ct << std::endl;

std::this_thread::sleep_for(std::chrono::seconds(1));
}
Expand Down
4 changes: 3 additions & 1 deletion iceoryx_examples/icedelivery/iox_publisher_with_history.cpp
Expand Up @@ -41,7 +41,7 @@ int main()
iox::popo::TypedPublisher<RadarObject> typedPublisher({"Radar", "FrontLeft", "Object"}, publisherOptions);
typedPublisher.offer();

float_t ct = 0.0;
double ct = 0.0;
while (!killswitch)
{
++ct;
Expand All @@ -55,6 +55,8 @@ int main()
sample.publish();
});

std::cout << "Sent value: " << ct << std::endl;

std::this_thread::sleep_for(std::chrono::milliseconds(400));
}

Expand Down
5 changes: 2 additions & 3 deletions iceoryx_examples/icedelivery/iox_subscriber_typed.cpp
Expand Up @@ -49,10 +49,9 @@ int main()
{
typedSubscriber.take()
.and_then([](iox::popo::Sample<const RadarObject>& object) {
std::cout << "Got value: (" << object->x << ", " << object->y << ", " << object->z << ")"
<< std::endl;
std::cout << "Got value: " << object->x << std::endl;
})
.if_empty([] { std::cout << "Didn't get a value, but do something anyway." << std::endl; })
.if_empty([] { std::cout << std::endl; })
.or_else([](iox::popo::ChunkReceiveError) { std::cout << "Error receiving chunk." << std::endl; });
}
else
Expand Down
5 changes: 2 additions & 3 deletions iceoryx_examples/icedelivery/iox_subscriber_untyped.cpp
Expand Up @@ -50,10 +50,9 @@ int main()
untypedSubscriber.take()
.and_then([](iox::popo::Sample<const void>& sample) {
auto object = static_cast<const RadarObject*>(sample.get());
std::cout << "Got value: (" << object->x << ", " << object->y << ", " << object->z << ")"
<< std::endl;
std::cout << "Got value: " << object->x << std::endl;
})
.if_empty([] { std::cout << "Didn't get a value, but do something anyway." << std::endl; })
.if_empty([] { std::cout << std::endl; })
.or_else([](iox::popo::ChunkReceiveError) { std::cout << "Error receiving chunk." << std::endl; });
}
else
Expand Down
7 changes: 3 additions & 4 deletions iceoryx_examples/icedelivery/iox_subscriber_with_history.cpp
Expand Up @@ -40,8 +40,8 @@ int main()
iox::popo::SubscriberOptions subscriberOptions;
subscriberOptions.queueCapacity = 10U;
// When starting the subscriber late it will miss the first samples which the
// publisher has send. The history ensures that we at least get the last 10
// samples send by the publisher when we subscribe.
// publisher has send. The history ensures that we at least get the last 5
// samples sent by the publisher when we subscribe (if at least 5 were already sent).
subscriberOptions.historyRequest = 5U;
iox::popo::TypedSubscriber<RadarObject> typedSubscriber({"Radar", "FrontLeft", "Object"}, subscriberOptions);
typedSubscriber.subscribe();
Expand All @@ -58,8 +58,7 @@ int main()
{
typedSubscriber.take()
.and_then([](iox::popo::Sample<const RadarObject>& object) {
std::cout << "Got value: (" << object->x << ", " << object->y << ", " << object->z << ")"
<< std::endl;
std::cout << "Got value: " << object->x << std::endl;
})
.if_empty([&] { hasMoreSamples = false; });
} while (hasMoreSamples);
Expand Down
20 changes: 11 additions & 9 deletions iceoryx_examples/icedelivery_on_c/README.md
Expand Up @@ -44,7 +44,7 @@ Let's take a look at the `receiving` function which comes with the
const uint64_t historyRequest = 10U;
const uint64_t queueCapacity = 5U;
iox_sub_storage_t subscriberStorage;
iox_sub_t subscriber = iox_sub_init(&subscriberStorage, "Radar", "FrontLeft", "Counter", queueCapacity, historyRequest);
iox_sub_t subscriber = iox_sub_init(&subscriberStorage, "Radar", "FrontLeft", "Object", queueCapacity, historyRequest);
```

3. We subscribe to the service.
Expand All @@ -63,8 +63,8 @@ Let's take a look at the `receiving` function which comes with the
const void* chunk = NULL;
while (ChunkReceiveError_SUCCESS == iox_sub_get_chunk(subscriber, &chunk))
{
const struct CounterTopic* sample = (const struct CounterTopic*)(chunk);
printf("Receiving: %u\n", sample->counter);
const struct RadarObject* sample = (const struct RadarObject*)(chunk);
printf("Got value: %.0f\n", sample->x);
iox_sub_release_chunk(subscriber, chunk);
}
}
Expand Down Expand Up @@ -112,7 +112,7 @@ Let's take a look at the `sending` function which comes with the
```c
const uint64_t historyRequest = 10U;
iox_pub_storage_t publisherStorage;
iox_pub_t publisher = iox_pub_init(&publisherStorage, "Radar", "FrontLeft", "Counter", historyRequest);
iox_pub_t publisher = iox_pub_init(&publisherStorage, "Radar", "FrontLeft", "Object", historyRequest);
```
3. We offer our service to the world.
```c
Expand All @@ -123,18 +123,20 @@ Let's take a look at the `sending` function which comes with the
incrementing number to all subscribers every send and print the
value of this number to the console.
```c
uint32_t ct = 0u;
double ct = 0.0;

while (!killswitch)
{
void* chunk = NULL;
if (AllocationResult_SUCCESS == iox_pub_allocate_chunk(publisher, &chunk, sizeof(struct CounterTopic)))
if (AllocationResult_SUCCESS == iox_pub_allocate_chunk(publisher, &chunk, sizeof(struct RadarObject)))
{
struct CounterTopic* sample = (struct CounterTopic*)chunk;
struct RadarObject* sample = (struct RadarObject*)chunk;

sample->counter = ct;
sample->x = ct;
sample->y = ct;
sample->z = ct;

printf("Sending: %u\n", ct);
printf("Sent value: %.0f\n", ct);

iox_pub_send_chunk(publisher, chunk);

Expand Down
14 changes: 8 additions & 6 deletions iceoryx_examples/icedelivery_on_c/ice_c_publisher.c
Expand Up @@ -36,22 +36,24 @@ void sending()

const uint64_t historyRequest = 10U;
iox_pub_storage_t publisherStorage;
iox_pub_t publisher = iox_pub_init(&publisherStorage, "Radar", "FrontLeft", "Counter", historyRequest);
iox_pub_t publisher = iox_pub_init(&publisherStorage, "Radar", "FrontLeft", "Object", historyRequest);

iox_pub_offer(publisher);

uint32_t ct = 0U;
double ct = 0.0;

while (!killswitch)
{
void* chunk = NULL;
if (AllocationResult_SUCCESS == iox_pub_allocate_chunk(publisher, &chunk, sizeof(struct CounterTopic)))
if (AllocationResult_SUCCESS == iox_pub_allocate_chunk(publisher, &chunk, sizeof(struct RadarObject)))
{
struct CounterTopic* sample = (struct CounterTopic*)chunk;
struct RadarObject* sample = (struct RadarObject*)chunk;

sample->counter = ct;
sample->x = ct;
sample->y = ct;
sample->z = ct;

printf("Sending: %u\n", ct);
printf("Sent value: %.0f\n", ct);

iox_pub_send_chunk(publisher, chunk);

Expand Down
6 changes: 3 additions & 3 deletions iceoryx_examples/icedelivery_on_c/ice_c_subscriber.c
Expand Up @@ -43,7 +43,7 @@ void receiving()
iox_sub_storage_t subscriberStorage;

iox_sub_t subscriber =
iox_sub_init(&subscriberStorage, "Radar", "FrontLeft", "Counter", queueCapacity, historyRequest);
iox_sub_init(&subscriberStorage, "Radar", "FrontLeft", "Object", queueCapacity, historyRequest);
iox_sub_subscribe(subscriber);

while (!killswitch)
Expand All @@ -55,8 +55,8 @@ void receiving()
// new sample every 400ms and we check for new samples only every second
while (ChunkReceiveResult_SUCCESS == iox_sub_get_chunk(subscriber, &chunk))
{
const struct CounterTopic* sample = (const struct CounterTopic*)(chunk);
printf("Receiving: %u\n", sample->counter);
const struct RadarObject* sample = (const struct RadarObject*)(chunk);
printf("Got value: %.0f\n", sample->x);
iox_sub_release_chunk(subscriber, chunk);
}
printf("\n");
Expand Down
6 changes: 4 additions & 2 deletions iceoryx_examples/icedelivery_on_c/topic_data.h
Expand Up @@ -17,9 +17,11 @@

#include <stdint.h>

struct CounterTopic
struct RadarObject
{
uint32_t counter;
double x;
double y;
double z;
};

#endif // IOX_EXAMPLES_ICEDELIVERY_TOPIC_DATA_HPP
2 changes: 1 addition & 1 deletion iceoryx_meta/tests.cmake
Expand Up @@ -18,7 +18,7 @@ if (BUILD_TEST)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/googletest ${CMAKE_BINARY_DIR}/dependencies/googletest/prebuild)

### create component list
set(COMPONENTS "posh" "utils")
set(COMPONENTS "utils" "posh")

### possible place for more extensions
if (DDS_GATEWAY)
Expand Down
7 changes: 5 additions & 2 deletions iceoryx_posh/include/iceoryx_posh/runtime/posh_runtime.hpp
Expand Up @@ -26,7 +26,9 @@
#include "iceoryx_posh/internal/runtime/shared_memory_user.hpp"
#include "iceoryx_posh/popo/subscriber_options.hpp"
#include "iceoryx_posh/runtime/port_config_info.hpp"
#include "iceoryx_utils/cxx/method_callback.hpp"
#include "iceoryx_utils/cxx/string.hpp"
#include "iceoryx_utils/internal/concurrent/periodic_task.hpp"

#include <atomic>
#include <map>
Expand Down Expand Up @@ -202,8 +204,9 @@ class PoshRuntime
void sendKeepAlive() noexcept;
static_assert(PROCESS_KEEP_ALIVE_INTERVAL > roudi::DISCOVERY_INTERVAL, "Keep alive interval too small");

/// @note the m_keepAliveTimer should always be the last member, so that it will be the first member to be detroyed
iox::posix::Timer m_keepAliveTimer{PROCESS_KEEP_ALIVE_INTERVAL, [&]() { this->sendKeepAlive(); }};
/// @note the m_keepAliveTask should always be the last member, so that it will be the first member to be destroyed
concurrent::PeriodicTask<cxx::MethodCallback<void>> m_keepAliveTask{
"KeepAlive", PROCESS_KEEP_ALIVE_INTERVAL, *this, &PoshRuntime::sendKeepAlive};
};

} // namespace runtime
Expand Down

0 comments on commit 0186384

Please sign in to comment.