Skip to content

Commit

Permalink
Merge pull request eclipse-iceoryx#699 from ApexAI/iox-#482-rework-ov…
Browse files Browse the repository at this point in the history
…erview

Iox eclipse-iceoryx#482 rework overview
  • Loading branch information
FerdinandSpitzschnueffler authored and marthtz committed May 12, 2021
2 parents 234a6bc + 2b51166 commit 7c3367c
Show file tree
Hide file tree
Showing 8 changed files with 344 additions and 729 deletions.
8 changes: 5 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ codebase follows these rules, things are work in progress.

1) **No heap is allowed**, static memory management hugely decreases the complexity of your software (e.g. cxx::vector
without heap)
2) **No exception are allowed**, all function and methods need to have `noexcept` in their signature
2) **No exceptions are allowed**, all function and methods need to have `noexcept` in their signature
3) **No undefined behavior**, zero-cost abstract is not feasible in high safety environments
4) **Use C++14**
5) **[Rule of Five](https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming))**, if there is a non-default
Expand All @@ -79,9 +79,11 @@ codebase follows these rules, things are work in progress.
our code may contain additions which are not compatible with the STL (e.g. `iox::cxx::vector::emplace_back()`
does return a bool)
7) **Always use `iox::log::Logger`**, instead of `printf()`
8) **Always use `iox::ErrorHandler()`**, instead of the direct STL calls
8) **Always use `iox::ErrorHandler()`**, when an error occurs that cannot or shall not be propagated via an
`iox::cxx::expected`, the `iox::ErrorHandler()` shall be used; exceptions are not allowed

See [error-handling.md](./doc/error-handling.md) for additional information about logging and error handling.
See [error-handling.md](https://github.com/eclipse-iceoryx/iceoryx/blob/master/doc/design/error-handling.md) for additional
information about logging and error handling.

### Naming conventions

Expand Down
6 changes: 3 additions & 3 deletions doc/aspice_swe3_4/swe_docu_guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ Here we provide a list with the most usual tags in iceoryx:
### Custom Tags
In iceoryx are also custom tags used for extended documentation like errors.
- `/// @concurrent` use this tag if the code is used in multithreading context for comments about it
- `/// @req` used to set links to a database with requirements, see [iceoryx_component.hpp](example/iceoryx_component/include/iceoryx_component.hpp)
- `/// @link` used to set general links additional information, see [iceoryx_component.hpp](example/iceoryx_component/include/iceoryx_component.hpp)
- `/// @req` used to set links to a database with requirements, see [iceoryx_component.hpp](example/iceoryx_component/include/example_component.hpp)
- `/// @link` used to set general links additional information, see [iceoryx_component.hpp](example/iceoryx_component/include/example_component.hpp)
- `/// @swcomponent` marks the relationship to the component
- `/// @error` used for describing the error behavior e.g. error-handler is called
- `/// @generatedcode` for marking code as generated
Expand Down Expand Up @@ -122,4 +122,4 @@ If you want to download the pdf files from the Pull-Requests or master build you

* Open the "Checks" view in the PR
* Open the "Details" link for the check `iceoryx-coverage-doxygen-ubuntu` in `Test Coverage + Doxygen Documentation`
* On the right side you find a menu button `Artifacts` which shows `iceoryx-pdf` as download link
* On the right side you find a menu button `Artifacts` which shows `iceoryx-pdf` as download link
187 changes: 0 additions & 187 deletions doc/design/fixedString.adoc

This file was deleted.

2 changes: 1 addition & 1 deletion doc/goals-non-goals.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,4 @@ that slow self-made IPC to communicate with his sensors because his parents want
makes it hard for him to react in real-time to dangerous incidents like flying coffee cups. When strolling through
the interwebs on a lonely evening, he finds out about iceoryx: Free-to-use, high-performance data transfer with low
runtime overhead, real-time support! Brilliant! Maybe even Robby's biggest wish for a network binding will come true,
so he can stream his favorite [video](https://www.youtube.com/watch?v=g5NkgZXWl0w) even faster!
so he can stream his favorite videos even faster!
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# How optional and error values are returned in iceoryx

Many parts of the iceoryx C++ API follow a functional programming approach and allow the user to specify functions
which handle the possible cases, e.g. what should happen when data is received.

This is very flexible but requires using the monadic types `cxx::expected` and `cxx::optional`, which we
introduce in the following sections.

## Optional

The type `iox::cxx::optional<T>` is used to indicate that there may or may not be a value of a specific type `T`
available. This is essentially the 'maybe [monad](https://en.wikipedia.org/wiki/Monad_(functional_programming))' in
functional programming. Assuming we have some optional (usually the result of some computation)

```cpp
optional<int> result = someComputation();
```

we can check for its value using

```cpp
if(result.has_value())
{
auto value = result.value();
// do something with the value
}
else
{
// handle the case that there is no value
}
```

A shorthand to get the value is

```cpp
auto value = *result;
```

!!! attention
Accessing the value if there is no value terminates the application, so it must be checked beforehand.

We can achieve the same with the functional approach by providing a function for both cases.

```cpp
result.and_then([](int& value) { /*do something with the value*/ })
.or_else([]() { /*handle the case that there is no value*/ });
```
Notice that we get the value by reference, so if a copy is desired it has to be created explicitly in the
[lambda](https://en.wikipedia.org/wiki/Anonymous_function#C++_(since_C++11)) or function we pass.
The optional can be initialized from a value directly
```cpp
optional<int> result = 73;
result = 37;
```

If the optional is default initialized, it is automatically set to its null value of type `iox::cxx::nullopt_t`.
This can be also done directly by using the constant `iox::cxx::nullopt`

```cpp
result = iox::cxx::nullopt;
```

For a complete list of available functions see
[`optional.hpp`](https://github.com/eclipse-iceoryx/iceoryx/blob/master/iceoryx_utils/include/iceoryx_utils/cxx/optional.hpp).
The `iox::cxx::optional` behaves like the [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional)
except that it does not throw exceptions and has no undefined behavior.

## Expected

`iox::cxx::expected<T, E>` generalizes `iox::cxx::optional` by admitting a value of another type `E` instead of
no value at all, i.e. it contains either a value of type `T` or `E`. In this way, `expected` is a special case of
the 'either monad'. It is usually used to pass a value of type `T` or an error that may have occurred, i.e. `E` is the
error type. `E` must contain a static member or an enum value called `INVALID_STATE`. Alternatively an
[`ErrorTypeAdapter`](https://github.com/eclipse-iceoryx/iceoryx/blob/5b1a0514e72514c2eae8a9d071d82a3905fedf8b/iceoryx_utils/include/iceoryx_utils/cxx/expected.hpp#L46)
can be implemented.

For more information on how it is used for error handling see
[error-handling.md](https://github.com/eclipse-iceoryx/iceoryx/blob/master/doc/design/error-handling.md).

Assume we have `E` as an error type, then we can create a value

```cpp
iox::cxx::expected<int, E> result(iox::cxx::success<int>(73));
```
and use the value or handle a potential error
```cpp
if (!result.has_error())
{
auto value = result.value();
// do something with the value
}
else
{
auto error = result.get_error();
// handle the error
}
```

If we need an error value, we set

```cpp
result = iox::cxx::error<E>(errorCode);
```

which assumes that `E` can be constructed from an `errorCode`.

We again can employ a functional approach like this:

```cpp
auto handleValue = [](int& value) { /*do something with the value*/ };
auto handleError = [](E& value) { /*handle the error*/ };
result.and_then(handleValue).or_else(handleError);
```
There are more convenience functions such as `value_or` which provides the value or an alternative specified by the
user. These can be found in
[`expected.hpp`](https://github.com/eclipse-iceoryx/iceoryx/blob/master/iceoryx_utils/include/iceoryx_utils/cxx/expected.hpp).
Note that when we move an `expected`, the origin is set to the error value `E::INVALID_STATE` and `has_error()` will
always return true:
```cpp
cxx::expected<int, E> result(iox::cxx::success<int>(1421));
cxx::expected<int, E> anotherResult = std::move(result);
if (result.has_error()) // is now true since it was moved
{
result.get_error(); // returns E::INVALID_STATE
}
```
Loading

0 comments on commit 7c3367c

Please sign in to comment.