Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use cetl::unbounded_variant for errors originating from the layers below LibCyphal #345

Open
pavel-kirienko opened this issue Apr 17, 2024 · 1 comment
Assignees
Labels
class-requirement Issue that can be traced back to a design requiement domain-production Pertains to the shippable code rather than any scaffolding priority-high status-help-wanted Issues that core maintainers do not have the time or expertise to work on.

Comments

@pavel-kirienko
Copy link
Member

A classic approach here would be to use inheritance directly, allowing the platform layer to define arbitrary error types derived from our PlatformError, like this.

However, it is impossible to return a polymorphic object by value directly when its runtime type is unknown; we need either heap (which is not an option) or a type-erased container like cetl::unbounded_variant (see inheritance without pointers).

We define a small set of well-known error types that can occur within the libcyphal middleware itself, such as ArgumentError, MemoryError, etc, and assume them to be rigid and non-extensible. Other error types are used to model errors originating from the lower layers, and they necessarily have to be arbitrarily extensible. We have several approaches here:

1. Use an opaque container:

using PlatformError = cetl::unbounded_variant<Footprint>;
//...
using AnyError = cetl::variant<ArgumentError, MemoryError, ..., PlatformError>;

This is straightforward, but one downside is that it may provide too much flexibility for the platform layer. For example, one could push an int into the opaque container, which is not a sensible approach to error handling.

2. Use by-value polymorphism:

class IPlatformError : public cetl::rtti_helper<...>  // rtti_helper can be avoided here
{
protected:
    IPlatformError() = default;
    virtual ~IPlatformError() = default;
};

using PlatformError = ImplementationCell<IPlatformError, cetl::unbounded_variant<Footprint>>;

ImplementationCell is a wrapper over unbounded_variant or any defined here: https://github.com/OpenCyphal-Garage/libcyphal/blob/main/docs/design/readme.md#type-erasure-without-pointers.

This solution restricts the set of error types that can be returned from the platform layer and allows us to define arbitrary polymorphic methods on them, like what.

@thirtytwobits please review

@pavel-kirienko pavel-kirienko added status-help-wanted Issues that core maintainers do not have the time or expertise to work on. domain-production Pertains to the shippable code rather than any scaffolding priority-high class-requirement Issue that can be traced back to a design requiement labels Apr 17, 2024
@thirtytwobits
Copy link
Contributor

Option 2 ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
class-requirement Issue that can be traced back to a design requiement domain-production Pertains to the shippable code rather than any scaffolding priority-high status-help-wanted Issues that core maintainers do not have the time or expertise to work on.
Projects
None yet
Development

No branches or pull requests

3 participants