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

Formatting thread::id, stacktrace_entry, and basic_stacktrace #3861

Merged

Conversation

JMazurkiewicz
Copy link
Contributor

@JMazurkiewicz JMazurkiewicz commented Jul 11, 2023

  • Add _Fill_align_and_width_specs, _Fill_align_and_width_specs_setter and _Fill_align_and_width_formatter types. They are use by formatters that accept only fill-and-align and width fields (thread::id and stacktrace_entry in this PR).
  • Move std::call_once from <mutex> to <xcall_once.h> to avoid circular dependency. I hope this is OK.
  • Implement WG21-P2693R1: formatters for thread::id, stacktrace_entry and basic_stacktrace.
  • Fix operator<<(thread::id) in all supported C++ modes. See LLVM-62073 for bug report and @mordante's rationale.
  • Add tests.
  • Close P2693R1 Formatting thread::id And stacktrace #3447.

@JMazurkiewicz JMazurkiewicz requested a review from a team as a code owner July 11, 2023 13:23
stl/inc/thread Outdated Show resolved Hide resolved
@cpplearner
Copy link
Contributor

Could _Specs_setter, _Chrono_specs_setter and the new _Fill_align_and_width_formatter share some common members? It's a bit awkward to have three identical definitions of _On_fill and others.

(Also, P2286R8 adds range-format-spec and tuple-format-spec, which are basically fill-and-align + width + type-specific options. It would be nice if the existing machinery can be reused when dealing with their fill, align, and width.)

@JMazurkiewicz
Copy link
Contributor Author

JMazurkiewicz commented Jul 11, 2023

Could _Specs_setter, _Chrono_specs_setter and the new _Fill_align_and_width_formatter share some common members? It's a bit awkward to have three identical definitions of _On_fill and others.

I agree, unifying those setters is necessary. I'd leave it for another PR though, since it would require editing another header (<chrono>) and this PR is already big enough.

@StephanTLavavej StephanTLavavej added format C++20/23 format cxx23 C++23 feature labels Jul 12, 2023
Comment on lines +3939 to +3946
struct _Fill_align_and_width_specs { // used by thread::id and stacktrace_entry formatters
int _Width = -1;
int _Dynamic_width_index = -1;
_Fmt_align _Alignment = _Fmt_align::_None;
uint8_t _Fill_length = 1;
// At most one codepoint (so one char32_t or four utf-8 char8_t).
_CharT _Fill[4 / sizeof(_CharT)] = {' '};
};
Copy link
Member

Choose a reason for hiding this comment

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

I suspect this could be unified with _Basic_format_specs and _Dynamic_format_specs, I need to work out what that would actually look like though, and it probably requires nontrivial inheritance.

@barcharcraz
Copy link
Member

At first glance things look pretty good, I'll see if I can figure out how you might be able to eliminate all the duplicate specs setter code without changing a bunch of chrono stuff next week.

Copy link
Member

@StephanTLavavej StephanTLavavej left a comment

Choose a reason for hiding this comment

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

Thanks! I'll validate and push changes...

stl/inc/thread Outdated Show resolved Hide resolved
stl/inc/thread Outdated Show resolved Hide resolved
stl/inc/stacktrace Outdated Show resolved Hide resolved
stl/inc/format Outdated Show resolved Hide resolved
tests/std/tests/P2693R1_text_formatting_thread_id/test.cpp Outdated Show resolved Hide resolved
tests/std/tests/P2693R1_text_formatting_thread_id/test.cpp Outdated Show resolved Hide resolved
tests/std/tests/P2693R1_text_formatting_thread_id/test.cpp Outdated Show resolved Hide resolved
@StephanTLavavej StephanTLavavej changed the title Formatting thread::id, stacktrace_entry and basic_stacktrace Formatting thread::id, stacktrace_entry, and basic_stacktrace Jul 19, 2023
Copy link
Member

@barcharcraz barcharcraz left a comment

Choose a reason for hiding this comment

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

In order to prevent the code duplication here we'd have to rearrange _Basic_format_specs and _Dynamic_format_specs, and I'm not sure we can do that without ABI impact.

If we want to unify things we could do something like:

template<class _CharT>
struct _Really_basic_format_specs {
    int _Width = -1;
    _Fmt_align _Alignment = _Fmt_align::_None;
    uint8_t _Fill_length  = 1;
    // At most one codepoint (so one char32_t or four utf-8 char8_t).
    _CharT _Fill[4 / sizeof(_CharT)] = {' '};
};



template <class _CharT>
struct _Basic_format_specs : _Really_basic_format_specs<_CharT> {
    int _Precision        = -1;
    char _Type            = '\0';
    _Fmt_sign _Sgn        = _Fmt_sign::_None;
    bool _Alt             = false;
    bool _Localized       = false;
    bool _Leading_zero    = false;
};

struct _Dynamic_width_format_specs {
    int _Dynamic_width_index = -1;
};

// used by thread::id and stacktrace_entry formatters
template <class _CharT>
struct _Fill_align_and_width_specs : _Really_basic_format_specs<_CharT>, _Dynamic_width_format_specs { };

template <class _CharT>
struct _Dynamic_format_specs : _Basic_format_specs<_CharT>, _Dynamic_width_format_specs {
    int _Dynamic_precision_index = -1;
};

The specs setter classes could be slightly refactored to use either CRTP or to just have a collection of static methods taking the specs to fill in as the first parameter (basically making the setter even closer to members of the specs classes).

Again, this changes the order of the specs members, and the spec class is included by-value as a member of all the formatters, which users are allowed to derive from. This is also a bigger refactor, so I'm comfortable leaving it for later.

@StephanTLavavej
Copy link
Member

Again, this changes the order of the specs members, and the spec class is included by-value as a member of all the formatters, which users are allowed to derive from.

That sounds like an unavoidably ABI-breaking change. Sounds like everyone's happy with a follow-up investigation; I suspect that no change will happen as a result.

@StephanTLavavej StephanTLavavej self-assigned this Jul 25, 2023
@StephanTLavavej

This comment was marked as outdated.

@StephanTLavavej

This comment was marked as resolved.

@StephanTLavavej StephanTLavavej removed their assignment Jul 27, 2023
@StephanTLavavej

This comment was marked as resolved.

@StephanTLavavej StephanTLavavej self-assigned this Jul 31, 2023
@StephanTLavavej

This comment was marked as resolved.

@StephanTLavavej
Copy link
Member

The failure appears to be consistently happening in fmt("{:{}}", frame, width) but I haven't been able to figure out what the problem is.

@StephanTLavavej StephanTLavavej removed their assignment Aug 1, 2023
@StephanTLavavej
Copy link
Member

I've pushed a defensive commit to use clamp() to avoid fill_width ever being negative. Let's see if this helps...

@StephanTLavavej StephanTLavavej self-assigned this Aug 3, 2023
@StephanTLavavej
Copy link
Member

I'm mirroring this to the MSVC-internal repo - please notify me if any further changes are pushed.

@StephanTLavavej StephanTLavavej merged commit ed8150e into microsoft:main Aug 3, 2023
35 checks passed
@StephanTLavavej
Copy link
Member

Thanks for implementing this feature! ⚙️ 😻 ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cxx23 C++23 feature format C++20/23 format
Projects
None yet
Development

Successfully merging this pull request may close these issues.

P2693R1 Formatting thread::id And stacktrace
5 participants