eclipse-iceoryx / eclipse-iceoryx/iceoryx

Implement `cxx::Future` and `cxx::Promise`

Open
#1,390 13 comments 1 reaction 0 assignees View on GitHub
enhancement
Dominant language
C++
Stars
2.2k
Forks
492
Avg merge
18h 57m
Merged PRs (30d)
1

Description

## Brief feature description

Automotive bindings like `ara::com` are using `std::Future` and `std::Promise` in [their APIs](https://github.com/eclipse-iceoryx/iceoryx-automotive-soa/blob/main/include/owl/types.hpp#L118-L124). However, they throw exceptions which is not in line with the iceoryx coding guidelines.

## Constraints

1. no dynamic memory
2. no exceptions
3. use safe STL (non-throwing, no dynamic memory, ...) and iceoryx hoofs only for implementation

## Goals

1. Support standard future use case
- create a promise p
- create a future f from p
- move p to another thread
- f waits for p to either set a value or an exception/error
- once p sets the value or error f unblocks
- value can be retrieved from the future
2. As close to STL syntax as possible
- generic values and exceptions/errors
- not completely possible due to constraints
3. Acceptable performance
- constraints lead to copies and (potentially) locking
- this would not be the case with dynamic memory, but most likely cannot be avoided without
4. Safeguard against misuse cases where possible
- at least detect them at runtime, e.g. broken promise
- how to communicate a misuse error (terminate?)

## Valid use

1. p sets value, f wakes up and is destroyed before p
2. p never creates a future (unusual but OK)

## Invalid use

1. create future (and wait) but destroy promise before setting a value or error (broken promise)
2. p creates multiple futures
3. create future from promise p, move p to another thread, move future
4. set the value or error multiple times at the promise
5. create another future after setting value (could be supported if it is deemed worth it)

## Limitations

1. Move semantics are limited (no dynamic memory)
- promise can be moved
- future cannot be moved once the promise may set a value
- there is at most one valid (active/waiting) future for each promise
2. As in STL, futures and promises are not copyable
- `shared_future` can be an extension (multiple futures wait for some promise)

## Implementation considerations

- in STL future and promise have a shared state
- shared state is allocated dynamically
- in icoeryx the shared state can exist in promise or future on the stack
- lifetime of this state is crucial (as long as a promise or future exists it has to point to a valid state)
- only one of them holds the state at any time
- initially the promise holds the state
- as soon as the promise creates a future, the state is moved to this future (hence the future must outlive the promise or the state moved back)
- moving the state may require locking (this may create very subtle races)
- a semaphore is part of the state to wait for the result/error
- the state contains the value, i.e. its size depends on the generic type parameter of the promise/future
- once the future was set it is not supposed to be set again, hence the future with its state may go out of scope (but needs to inform the promise to prevent accessing the state)

## Open Issues
Refers to prototype implementation in https://github.com/MatthiasKillat/iceoryx/tree/iox-futures-experimental

- clean up code
- testing (API, use cases and error cases where possible)
- proper definition of all misuse cases
- analysis of potential race conditions and fixes (or stated as further limitation)
- optimize state locking (may not be needed in some cases)
- remove exceptions (exist temporary, thrown in misuse cases)
- API changes to communicate errors (as we cannot use exceptions, use `expected`?)
- limits the error type to one `E` (can be circumvented with error inheritance hierarchy if needed)
- optional syntactic sugar, e.g. `std::packaged_task`

## Detailed information

* [x] Analyse feasibility of such an implementation
* [ ] Check how API could be as close to the STL but with using `cxx::expected`
* [ ] Implement exception-free, stack-based `cxx::Future`
* [ ] Implement exception-free, stack-based `cxx::Promise`

Contributor guide

Open the contributing guide

Research direction

Start by reviewing the referenced iox-futures-experimental prototype and the automotive API usage in include/owl/types.hpp. Define the exception-free, stack-based cxx::Future and cxx::Promise behavior against the listed valid and invalid cases, then cover the API, use cases, error cases, and race-condition concerns described in the issue.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
backend-api-design
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.