Skip to content

Commit

Permalink
Merge pull request #454 from elfenpiff/iox2-390-c-cxx-examples
Browse files Browse the repository at this point in the history
[#390] c cxx examples
  • Loading branch information
elfenpiff authored Oct 9, 2024
2 parents ec5867f + 1436d6a commit ca22976
Show file tree
Hide file tree
Showing 17 changed files with 701 additions and 16 deletions.
2 changes: 1 addition & 1 deletion config/iceoryx2.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ subscriber-expired-connection-buffer = 128
max-listeners = 16
max-notifiers = 16
max-nodes = 36
event-id-max-value = 32
event-id-max-value = 4294967295
1 change: 1 addition & 0 deletions doc/release-notes/iceoryx2-unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
-->

* Rename `NodeEvent` into `WaitEvent` [#390](https://github.com/eclipse-iceoryx/iceoryx2/issues/390)
* Remove ACL dependency [#457](https://github.com/eclipse-iceoryx/iceoryx2/issues/457)

### Workflow

Expand Down
24 changes: 12 additions & 12 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,15 @@ These types are demonstrated in the complex data types example.

## Overview

| Name | Language | Description |
| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| complex data types | [C++](cxx/complex_data_types) [Rust](rust/complex_data_types) | Send zero-copy compatible versions of `Vec` and `String`. Introduces `PlacementDefault` trait for large data types to perform an in place initialization where otherwise a stack overflow would be encountered. |
| discovery | [C](c/discovery) [C++](cxx/discovery) [Rust](rust/discovery) | List all available services in a system. |
| docker | [all](rust/docker) | Communicate between different docker containers and the host. |
| domains | [C](c/domains) [C++](cxx/domains) [Rust](rust/domains) | Establish separate domains that operate independently from one another. |
| event | [C](c/event) [C++](cxx/event) [Rust](rust/event) | Push notifications - send event signals to wakeup processes that are waiting for them. |
| event multiplexing | [Rust](rust/event_multiplexing) | Wait on multiple listeners or sockets with a single call. The WaitSet demultiplexes incoming events and notifies the user. |
| publish subscribe | [C](c/publish_subscribe) [C++](cxx/publish_subscribe) [Rust](rust/publish_subscribe) | Communication between multiple processes with a [publish subscribe messaging pattern](https://en.wikipedia.org/wiki/Publish–subscribe_pattern). |
| publish subscribe dynamic data | [Rust](rust/publish_subscribe_dynamic_data) | Communication between multiple processes with a [publish subscribe messaging pattern](https://en.wikipedia.org/wiki/Publish–subscribe_pattern) and payload data that consists of a slice of shared memory compatible types. |
| publish subscribe with user header | [C](c/publish_subscribe_with_user_header) [C++](cxx/publish_subscribe_with_user_header) [Rust](rust/publish_subscribe_with_user_header) | Add a user header to the payload (samples) to transfer additional information. |
| service attributes | [Rust](rust/service_attributes) | Creates a service with custom attributes that are available to every endpoint. If the attributes are not compatible the service will not open. |
| Name | Language | Description |
| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| complex data types | [Rust](rust/complex_data_types) | Send zero-copy compatible versions of `Vec` and `String`. Introduces `PlacementDefault` trait for large data types to perform an in place initialization where otherwise a stack overflow would be encountered. |
| discovery | [C](c/discovery) [C++](cxx/discovery) [Rust](rust/discovery) | List all available services in a system. |
| docker | [all](rust/docker) | Communicate between different docker containers and the host. |
| domains | [C](c/domains) [C++](cxx/domains) [Rust](rust/domains) | Establish separate domains that operate independently from one another. |
| event | [C](c/event) [C++](cxx/event) [Rust](rust/event) | Push notifications - send event signals to wakeup processes that are waiting for them. |
| event multiplexing | [C](c/event_multiplexing) [C++](cxx/event_multiplexing) [Rust](rust/event_multiplexing) | Wait on multiple listeners or sockets with a single call. The WaitSet demultiplexes incoming events and notifies the user. |
| publish subscribe | [C](c/publish_subscribe) [C++](cxx/publish_subscribe) [Rust](rust/publish_subscribe) | Communication between multiple processes with a [publish subscribe messaging pattern](https://en.wikipedia.org/wiki/Publish–subscribe_pattern). |
| publish subscribe dynamic data | [Rust](rust/publish_subscribe_dynamic_data) | Communication between multiple processes with a [publish subscribe messaging pattern](https://en.wikipedia.org/wiki/Publish–subscribe_pattern) and payload data that has a dynamic size. |
| publish subscribe with user header | [C](c/publish_subscribe_with_user_header) [C++](cxx/publish_subscribe_with_user_header) [Rust](rust/publish_subscribe_with_user_header) | Add a user header to the payload (samples) to transfer additional information. |
| service attributes | [Rust](rust/service_attributes) | Creates a service with custom attributes that are available to every endpoint. If the attributes are not compatible the service will not open. |
1 change: 1 addition & 0 deletions examples/c/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ project(examples_c LANGUAGES C)
add_subdirectory(discovery)
add_subdirectory(domains)
add_subdirectory(event)
add_subdirectory(event_multiplexing)
add_subdirectory(publish_subscribe)
add_subdirectory(publish_subscribe_with_user_header)
33 changes: 33 additions & 0 deletions examples/c/event_multiplexing/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Copyright (c) 2024 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache Software License 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0, or the MIT license
# which is available at https://opensource.org/licenses/MIT.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT

load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")

cc_binary(
name = "example_c_event_multiplexing_wait",
srcs = [
"src/wait.c",
],
deps = [
"//:iceoryx2-c",
],
)

cc_binary(
name = "example_c_event_multiplexing_notifier",
srcs = [
"src/notifier.c",
],
deps = [
"//:iceoryx2-c",
],
)
22 changes: 22 additions & 0 deletions examples/c/event_multiplexing/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright (c) 2024 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache Software License 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0, or the MIT license
# which is available at https://opensource.org/licenses/MIT.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT

cmake_minimum_required(VERSION 3.22)
project(example_c_event_multiplexing LANGUAGES C)

find_package(iceoryx2-c 0.4.1 REQUIRED)

add_executable(example_c_event_multiplexing_wait src/wait.c)
target_link_libraries(example_c_event_multiplexing_wait iceoryx2-c::static-lib)

add_executable(example_c_event_multiplexing_notifier src/notifier.c)
target_link_libraries(example_c_event_multiplexing_notifier iceoryx2-c::static-lib)
55 changes: 55 additions & 0 deletions examples/c/event_multiplexing/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Event

Before proceeding, all dependencies need to be installed. You can find
instructions in the [C Examples Readme](../README.md).

## Running The Example

This example demonstrates iceoryx2's event multiplexing mechanism,
called the `WaitSet`. It allows waiting, with a single call, on
multiple `Listener` ports as well as external file descriptor-based
events such as `sockets`.

In this setup, the `wait` process monitors two services, which the
user can specify via the command line option `-s` and `-t`.
The `notifier` can define the service to which it will send event
notifications using the `-s` option and specify the event ID with
the `-e` option.

In the example below, we are waiting for events on the services `fuu` and
`bar`. Service `fuu` is notified with event ID `123`, and service `bar` is
notified with event ID `456`.

### Terminal 1

```sh
./target/ffi/build/examples/c/event_multiplexing/example_c_event_multiplexing_wait fuu bar
```

### Terminal 2

```sh
./target/ffi/build/examples/c/event_multiplexing/example_c_event_multiplexing_notifier 123 fuu
```

### Terminal 3

```sh
./target/ffi/build/examples/c/event_multiplexing/example_c_event_multiplexing_notifier 456 bar
```

Feel free to instantiate multiple notifiers for the same service with the same
or different event id's. Or to for different services.

## Technical Details

The `iox2_waitset_t` utilizes `epoll`, `select`, or other event-multiplexing
mechanisms. Before the `iox2_waitset_t` can monitor a specific event, it must
first be attached using `iox2_waitset_attach_notification()`, which returns a
RAII `iox2_waitset_guard_t`. This `Guard` automatically detaches the attachment
when it is cleaned up with `iox2_waitset_guard_drop()`.

The `iox2_waitset_wait_and_process()` call requires a callback that is invoked
for each triggered attachment and provides the `iox2_waitset_attachment_id_h`.
The user can either use `iox2_waitset_attachment_id_has_event_from()` to
identify the object associated with the `iox2_waitset_attachment_id_h`.
97 changes: 97 additions & 0 deletions examples/c/event_multiplexing/src/notifier.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright (c) 2024 Contributors to the Eclipse Foundation
//
// See the NOTICE file(s) distributed with this work for additional
// information regarding copyright ownership.
//
// This program and the accompanying materials are made available under the
// terms of the Apache Software License 2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license
// which is available at https://opensource.org/licenses/MIT.
//
// SPDX-License-Identifier: Apache-2.0 OR MIT

#include "iox2/iceoryx2.h"

#include <stdint.h>
#include <stdio.h>
#include <string.h>

const int BASE_10 = 10;

#ifdef _WIN64
#include <windows.h>
#define sleep Sleep
#else
#include <unistd.h>
#endif

int main(int argc, char** argv) {
if (argc != 3) {
printf("Usage: %s EVENT_ID SERVICE_NAME\n", argv[0]);
return -1;
}

size_t event_id_value = strtoull(argv[1], NULL, BASE_10);

// create new node
iox2_node_builder_h node_builder_handle = iox2_node_builder_new(NULL);
iox2_node_h node_handle = NULL;
if (iox2_node_builder_create(node_builder_handle, NULL, iox2_service_type_e_IPC, &node_handle) != IOX2_OK) {
printf("Could not create node!\n");
goto end;
}

// create service name
const char* service_name_value = argv[2];
iox2_service_name_h service_name = NULL;
if (iox2_service_name_new(NULL, service_name_value, strlen(service_name_value), &service_name) != IOX2_OK) {
printf("Unable to create service name!\n");
goto drop_node;
}

// create service
iox2_service_name_ptr service_name_ptr = iox2_cast_service_name_ptr(service_name);
iox2_service_builder_h service_builder = iox2_node_service_builder(&node_handle, NULL, service_name_ptr);
iox2_service_builder_event_h service_builder_event = iox2_service_builder_event(service_builder);
iox2_port_factory_event_h service = NULL;
if (iox2_service_builder_event_open_or_create(service_builder_event, NULL, &service) != IOX2_OK) {
printf("Unable to create service!\n");
goto drop_node;
}

// create notifier
iox2_port_factory_notifier_builder_h notifier_builder = iox2_port_factory_event_notifier_builder(&service, NULL);
iox2_notifier_h notifier = NULL;
if (iox2_port_factory_notifier_builder_create(notifier_builder, NULL, &notifier) != IOX2_OK) {
printf("Unable to create notifier!\n");
goto drop_service;
}

// notifier with a period of 1 second
while (iox2_node_wait(&node_handle, 0, 0) == IOX2_OK) {
iox2_event_id_t event_id = { .value = event_id_value }; // NOLINT
if (iox2_notifier_notify_with_custom_event_id(&notifier, &event_id, NULL) != IOX2_OK) {
printf("Failed to notify listener!\n");
goto drop_notifier;
}

printf("[service: \"%s\"] Trigger event with id %lu ...\n", argv[2], (long unsigned) event_id.value);

sleep(1);
}

drop_notifier:
iox2_notifier_drop(notifier);

drop_service:
iox2_port_factory_event_drop(service);

drop_service_name:
iox2_service_name_drop(service_name);

drop_node:
iox2_node_drop(node_handle);

end:
return 0;
}
Loading

0 comments on commit ca22976

Please sign in to comment.