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

Switch from ESTD to ETL #58

Open
wants to merge 23 commits into
base: main
Choose a base branch
from

Conversation

rolandreichweinbmw
Copy link
Contributor

As being discussed in #51 , this is a first request for review via pull request.

@marcmo
Copy link
Contributor

marcmo commented Feb 8, 2025

thanks for your PR. It's impressive...it's massive! there is a lot of code that still needs formatting and it does not yet compile—those 2 things we need to solve first.

@rolandreichweinbmw
Copy link
Contributor Author

rolandreichweinbmw commented Feb 8, 2025

Regarding code formatting: I did as "treefmt" suggested.

@rolandreichweinbmw
Copy link
Contributor Author

rolandreichweinbmw commented Feb 8, 2025

Regarding compile: For me, it compiles and runs (on C++14).

Update: I also fixed it for the CI builds C++17 and C++20.

Or do you mean a different compile error I'm not aware of?

I compiled:

  • Unit tests
  • POSIX
  • S32K148

@rolandreichweinbmw rolandreichweinbmw force-pushed the use-etl branch 3 times, most recently from b385542 to 80dff0c Compare February 8, 2025 23:08
@rolandreichweinbmw
Copy link
Contributor Author

rolandreichweinbmw commented Feb 9, 2025

BTW: I'm using my fork/branch of ETL at https://github.com/rolandreichweinbmw/etl/tree/openbsw-replace-estd - just for your reference.

It includes some additions that I already contributed upstream, but no ETL release happened yet.

Copy link

@christian-schilling christian-schilling left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm raising a few points where I see etl being a step back from estl to put them up for discussion.
Apart from those we should think about how to treat etl and it's development. Do we want to upstream changes? Maintain patches? Keep it as is? Maintain an "add-on" library for missing pieces (like the ones I commented on).

Also I'm wondering if we really gain a lot by adopting etl. Just because we can does not mean we should.

::util::logger::DOCAN);
}

void DoCanSystem::init()
{
_classicAddressingFilter.init(::estd::make_slice(_addresses), ::estd::make_slice(_codecs));
_classicAddressingFilter.init(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there no comparable make_span helpers in etl that offer type deduction? I think it's quite beneficial to have/use those.

Copy link
Contributor Author

@rolandreichweinbmw rolandreichweinbmw Feb 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that they are really helpful.

There are deduction guides to the etl::span ctors:

https://github.com/ETLCPP/etl/blob/99d75375060b61aae49bb2fc06349b45cb2c3380/include/etl/span.h#L750

Unfortunately, only available w/ ETL_USING_CPP17

Maybe we can consider switching to C++17 in OpenBSW soon? :-)

For C++14, I can provide etl::make_span helper as we know from estd.

Update:
See: https://github.com/rolandreichweinbmw/etl/tree/span-make-span
And: ETLCPP/etl#1027

Now using it accordingly here.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed not sure why it was not added to etl, because they have make_array for example. Could be a suggestion for ETL

@@ -52,7 +53,9 @@ class EcuIdList

uint16_t getSize() const
{
return (fBufferLength == 0U) ? 0U : ::estd::read_be<uint16_t>(fpData);
return (fBufferLength == 0U)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is quite a step back in readability. I wonder if this can be expressed more concisely with etl.
One of the things we tried to achieve with estl was to eleminate the need to use reinterpret_cast from most code as far as possible by providing safer alternatives. One reasoning for this is also that reinterpret_cast often triggers warnings with safty related rulesets and using a safe wrapper api seems like a better approach over always adding suppression comments for those warnings.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I think the goal of ETL is also to achieve that "less usage of reinterpret_cast". Probably there is some other workaround for this specific use-case. Didn't try that out myself though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree!

That's why I contributed two alternative solutions to ETL some time ago:

I haven't used it yet in the above OpenBSW line since upstream has not decided yet which one to merge.

@@ -248,8 +258,9 @@ void TaskInitializer<Adapter>::create(
TaskFunctionType const taskFunction,
TaskConfigType const& config)
{
::estd::slice<uint8_t> bytes = ::estd::make_slice(stack).template reinterpret_as<uint8_t>();
::estd::memory::align(alignof(StackType_t), bytes);
::etl::span<uint8_t> bytes = ::etl::span<uint8_t>(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another case of reinterpret_cast being reintroduced in place of an api specifially designed to avoid it. (reinterpret_as, which is safer as it also includes the length adjustment calculations)

Copy link

@filipe-cuim filipe-cuim Feb 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed! But I wonder if this could be done in another way. Or if span could be construct in a different manner, because etl also offers reinterpret_as in etl/span.h. Haven't had the time to try that out myself.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I already contributed span::reinterpret_as() some time ago at:

https://github.com/rolandreichweinbmw/etl/tree/span-advance-copy-reinterpret-as

(Not yet available in upstream release, but we can already use it if you like as it is available in the ETL copy in this PR.)

{
(void)lastFrameIndex;
if (!_sendPending)
{
::estd::slice<uint8_t> payload = ::estd::slice<uint8_t>::from_pointer(
::etl::span<uint8_t> payload(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We chose to use from_pointer intead of overloading the constructor to make this less-safe and therefore less preferable way of creating slices/spans easier to spot.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. Could be something to suggest also for ETL

::estd::slice<uint8_t> payload = payloadBuffer;
EXPECT_TRUE(::estd::memory::is_equal(expectedPayload, payload));
::etl::span<uint8_t> payload = payloadBuffer;
EXPECT_TRUE(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think here the estl api was way better. It also has different behaviour, checking the equality of the sizes. However it does look like etl has etl::eqal, why not use that here?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed. We could have used etl::equal here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Adjusted accordingly.

frame.id = *reinterpret_cast<::etl::be_uint32_t*>(data.data());
data = data.subspan(sizeof(etl::be_uint32_t));
::etl::mem_copy(data.begin(), data.end(), frame.data.begin());
frame.data = frame.data.subspan(0, data.size());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.trim() as an inplace operation was introduced because some compilers used significantly more stack space when using .subslice(). This may or may not be an issue with the compilers being used in the future, but it certainly was quite significant in the past.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no knowledge about this issue, but subspan seems more clear than trim. I know estd also has subslice, but they seem to be doing the same thing (both etl::span::subspan and estd::slice::subslice).
Also the fact that trim may reset the size of the slice to zero seems to be strange in my view (even though it is documented).
But really not sure about this point.

@@ -84,7 +85,7 @@ inline ::estd::slice<uint8_t> ForwardingReader::peek() const
inline void ForwardingReader::release()
{
// If _destinationData is an empty slice, copy will not copy any data.
(void)::estd::memory::copy(_destinationData, _sourceData);
(void)::etl::mem_copy(_sourceData.begin(), _sourceData.end(), _destinationData.begin());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

estd::memory::copy is safer here as it also checks the destination length, which etl::mem_copy obviously can't.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we want safe copies, etl also offers that in copy_s in etl/algorithm.h
Also etl::mem_copy shouldn't check the length since it is a low level copy (basically memcpy but with pointers of the same time), so in this case it makes sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right.

When I previously contributed this addition to ETL:

ETLCPP/etl#1024
https://github.com/rolandreichweinbmw/etl/tree/span-advance-copy-reinterpret-as

... then I better also use it. :-)

Adjusting accordingly.

auto const v = ::estd::be_uint32_t::make(data);
return appendData(v.bytes, 4) == 4;
auto const v = ::etl::be_uint32_t(data);
return appendData(static_cast<uint8_t const*>(v.data()), 4) == 4;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the estl api is more clear here.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the static_cast wasn't needed here. The method etl::unaligned_type_common::data() already returns a const uint8_t*.
Honestly since data is used on most containers to get a pointer to its raw buffer, I think data seems more aligned with the rest of the apis.
About the make method, seems to be a bit redundant.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree. I removed static_cast.

@rolandreichweinbmw
Copy link
Contributor Author

rolandreichweinbmw commented Feb 10, 2025

I'm raising a few points where I see etl being a step back from estl to put them up for discussion. Apart from those we should think about how to treat etl and it's development. Do we want to upstream changes? Maintain patches? Keep it as is? Maintain an "add-on" library for missing pieces (like the ones I commented on).

Also I'm wondering if we really gain a lot by adopting etl. Just because we can does not mean we should.

During the process for this PR, I already contributed some additions to ETL to easen its use in OpenBSW, and the author is quite responsive:

https://github.com/ETLCPP/etl/issues?q=is%3Apr%20author%3Arolandreichweinbmw

Most of it he already merged, but unfortunately, they are not yet in the master branch or released yet due to the ETL development process.

However, I'm maintaining the changes relevant to OpenBSW in:

https://github.com/rolandreichweinbmw/etl/tree/openbsw-replace-estd - see also the individual feature branches.

I think for this purpose, we can maintain a fork or branches for changes not yet released in upstream ETL even though we should contribute all of it.

One point for ETL is that some of the features I would like to contribute to OpenBSW are already based on ETL. And ETL is being used in projects where I would like to merge OpenBSW. Apart from ETL being established in the industry and public since many years.

@rolandreichweinbmw
Copy link
Contributor Author

Just updated the branch and PR with new ETL upstream update, based on new ETL version 20.40.0, but with yet unmerged changes upstream that we need for easy switchover of OpenBSW to ETL. (As before, copied into the openbsw branch "use-etl".)

New ETL branch with those additions for reference is: https://github.com/rolandreichweinbmw/etl/tree/openbsw-replace-estd

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants