dominicm00 / ham

A meaty Jam build tool replacement

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Refactor memory and lifetime management

dominicm00 opened this issue · comments

Ham data classes derive from Referenceable as a replacement to smart pointers, but have a critical flaw; Referenceable objects cannot be const if their reference count is to be modified. This greatly limits the use of const throughout the codebase despite the fact that most Ham data is immutable after parsing, and causes difficult to resolve conflicts between const and non-const interfaces.

To resolve this, we should move to a more standard memory and lifetime management system, including:

  • Using shared_ptr instead of Referenceable
  • Removing manual memory management (e.g. the custom String classes)
  • Throwing exceptions when constructors fail

PRs:

Using shared_ptr instead of Referenceable

Or you can just use mutable to bypass const.

Removing manual memory management (e.g. the custom String classes)

These are derived from Haiku's string classes and make the codebase much more Haiku-friendly, it would be best to keep these around, please...

Using shared_ptr instead of Referenceable

Or you can just use mutable to bypass const.

The goal of the project is to (re)write ham to leverage modern C++ standards. Referenceable is a relic from before std::shared_ptr. Why is Referenceable worth saving?

Removing manual memory management (e.g. the custom String classes)

These are derived from Haiku's string classes and make the codebase much more Haiku-friendly, it would be best to keep these around, please...

Other than nostalgia, why? std::string is far from perfect, but Haiku's string classes are a nostalgia to the 90s and do not add any value in this particular project. It will likely make dominicm00's work harder, as he is leveraging other parts of the standard library, which by design will be much more friendly to std::string than to a custom string class.

The goal of the project is to (re)write ham to leverage modern C++ standards.

That may be one of the goals, but the ultimate goal is to make ham a viable replacement for jam. Unless these classes are really getting in the way, why work on this before that's done?

Other than nostalgia, why? std::string is far from perfect

that's a bit of an understatement. It lacks quite a lot of operations that are vital in string processing (e.g. split/join, replace-all, starts-with, ends-with to say the least) such that one usually has to write helper functions to use it when doing serious string processing. On the other hand, Haiku's string classes don't lack those operations and have much friendlier ergonomics in general.

Other than nostalgia, why? std::string is far from perfect

that's a bit of an understatement. It lacks quite a lot of operations that are vital in string processing (e.g. split/join, replace-all, starts-with, ends-with to say the least) such that one usually has to write helper functions to use it when doing serious string processing. On the other hand, Haiku's string classes don't lack those operations and have much friendlier ergonomics in general.

That's no longer true, C++ 20 introduces starts_with() and ends_with(), and there has always been append() and 'replace()`. and since std::string has iterators, it also supports many of the algorithms in the standard library.

Having said that, I think it can go either way, especially now that there seems to be a bug in std::ranges, though it is not entirely clear to me whether that's a bug in clang or the C++ spec in general.

The goal of the project is to (re)write ham to leverage modern C++ standards.

That may be one of the goals, but the ultimate goal is to make ham a viable replacement for jam. Unless these classes are really getting in the way, why work on this before that's done?

I agree; I paused working on this issue until Ham is in a place (i.e. building Haiku successfully) where I feel comfortable doing some refactoring.

Other than nostalgia, why? std::string is far from perfect

that's a bit of an understatement. It lacks quite a lot of operations that are vital in string processing (e.g. split/join, replace-all, starts-with, ends-with to say the least) such that one usually has to write helper functions to use it when doing serious string processing. On the other hand, Haiku's string classes don't lack those operations and have much friendlier ergonomics in general.

I don't quite understand what's wrong with helper functions, especially when you'd need to write the functionality anyways for a custom class. If it's just a syntax issue of being able to do str.myFunction(), you could have a class like MyString : public std::string to extend the standard API instead of replacing it.

My hope is for Ham to be not just a good project for Haiku, but for C++ in general so other projects can use it comfortably. I think sticking close to the standard library where possible is a good step towards that. The STL has issues, but in my opinion re-implementing standard containers is not sustainable.

That said, I understand wanting to completely control the ergonomics of your data structures. I think my decision is specifically based on:

  • The modern features being added that come for free with STL types, and
  • Reducing the surface area of the project as much as possible
  • Keeping to the expectations (especially in terms of memory management) of a modern C++ project
  • Reducing fragmentation, both with the C++ ecosystem and internally

As an example of the last point, Ham data structures expose one of:

  • A HasNext()/Next() iterator (not compatible with STL or enhanced for loops)
  • A standard iterator from an STL type
  • No iterator at all (needing Size()/ElementAt())

It's very easy to end up with situations like the above, where it's difficult to completely hide the STL API and interfaces are implemented inconsistently.

That's no longer true, C++ 20 introduces starts_with() and ends_with(), and there has always been append() and 'replace()`. and since std::string has iterators, it also supports many of the algorithms in the standard library.

Having said that, I think it can go either way, especially now that there seems to be a bug in std::ranges, though it is not entirely clear to me whether that's a bug in clang or the C++ spec in general.

The bug is specifically with Clang's parsing of the GNU standard library. Clang should work with libc++, and GCC is unaffected. It only caused some pain for me because I use clangd for my IDE features, meaning I thought there were nonsensical errors even though GCC compilation would have worked.