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

Optimize println() overloads added in P3142R0 #4672

Merged
merged 12 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions stl/inc/__msvc_filebuf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,9 +384,9 @@ class basic_filebuf : public basic_streambuf<_Elem, _Traits> { // stream buffer
}

#if _HAS_CXX23 && defined(_CPPRTTI)
template <class _Filebuf_type>
friend ios_base::iostate _Print_noformat_unicode(ostream&, string_view);
#endif
template <class _UnicodeConsoleFn, class _FallbackFn, class _Filebuf_type>
friend ios_base::iostate _Do_on_maybe_unicode_console(ostream&, _UnicodeConsoleFn, _FallbackFn);
#endif // ^^^ _HAS_CXX23 && defined(_CPPRTTI) ^^^

protected:
int_type __CLR_OR_THIS_CALL overflow(int_type _Meta = _Traits::eof()) override { // put an element to stream
Expand Down
3 changes: 3 additions & 0 deletions stl/inc/__msvc_print.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ _NODISCARD _Success_(return == __std_win_error::_Success) __std_win_error
__stdcall __std_print_to_unicode_console(_In_ __std_unicode_console_handle _Console_handle,
_In_reads_(_Str_size) const char* _Str, _In_ size_t _Str_size) noexcept;

_NODISCARD _Success_(return == __std_win_error::_Success) __std_win_error
__stdcall __std_print_newline_only_to_unicode_console(_In_ __std_unicode_console_handle _Console_handle) noexcept;

} // extern "C"

_STD_BEGIN
Expand Down
66 changes: 60 additions & 6 deletions stl/inc/ostream
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,24 @@ ios_base::iostate _Print_noformat_nonunicode(ostream& _Ostr, const string_view _
return _State;
}

template <int = 0>
ios_base::iostate _Print_newline_only_nonunicode(ostream& _Ostr) {
// *LOCKED*
//
// This function is called from a context in which an ostream::sentry has been
// constructed.
ios_base::iostate _State = ios_base::goodbit;

_TRY_IO_BEGIN
const bool _Was_insertion_successful = _Ostr.rdbuf()->sputc('\n') == '\n';
if (!_Was_insertion_successful) [[unlikely]] {
_State |= ios_base::badbit;
}
_CATCH_IO_(ios_base, _Ostr)

return _State;
}

template <int = 0>
void _Vprint_nonunicode_impl(
const _Add_newline _Add_nl, ostream& _Ostr, const string_view _Fmt_str, const format_args _Fmt_args) {
Expand All @@ -117,8 +135,9 @@ void _Vprint_nonunicode_impl(
_Ostr.setstate(_State);
}

template <class _Filebuf_type = filebuf>
ios_base::iostate _Print_noformat_unicode(ostream& _Ostr, const string_view _Str) {
template <class _UnicodeConsoleFn, class _FallbackFn, class _Filebuf_type = filebuf>
ios_base::iostate _Do_on_maybe_unicode_console(
ostream& _Ostr, _UnicodeConsoleFn _Unicode_console_func, _FallbackFn _Fallback_func) {
// *LOCKED*
//
// This function is called from a context in which an ostream::sentry has been
Expand All @@ -136,7 +155,7 @@ ios_base::iostate _Print_noformat_unicode(ostream& _Ostr, const string_view _Str

// If we got nullptr, then it probably isn't being used for a unicode console...
if (_Filebuf == nullptr) {
_State |= _STD _Print_noformat_nonunicode(_Ostr, _Str);
_State |= _Fallback_func();
return _State;
}

Expand Down Expand Up @@ -175,18 +194,40 @@ ios_base::iostate _Print_noformat_unicode(ostream& _Ostr, const string_view _Str
}

const __std_win_error _Unicode_console_print_result =
__std_print_to_unicode_console(_Unicode_console_retrieval_result._Console_handle, _Str.data(), _Str.size());
_Unicode_console_func(_Unicode_console_retrieval_result._Console_handle);
if (_Unicode_console_print_result != __std_win_error::_Success) [[unlikely]] {
_State |= ios_base::badbit;
}
_CATCH_IO_(ios_base, _Ostr)
} else {
_State |= _STD _Print_noformat_nonunicode(_Ostr, _Str);
_State |= _Fallback_func();
}

return _State;
}

template <int = 0>
ios_base::iostate _Print_noformat_unicode(ostream& _Ostr, const string_view _Str) {
const auto _Unicode_console = [&](const __std_unicode_console_handle _Console_handle) {
return __std_print_to_unicode_console(_Console_handle, _Str.data(), _Str.size());
};

const auto _Fallback = [&] { return _STD _Print_noformat_nonunicode(_Ostr, _Str); };

return _STD _Do_on_maybe_unicode_console(_Ostr, _Unicode_console, _Fallback);
}

template <int = 0>
ios_base::iostate _Print_newline_only_unicode(ostream& _Ostr) {
const auto _Unicode_console = [](const __std_unicode_console_handle _Console_handle) {
return __std_print_newline_only_to_unicode_console(_Console_handle);
};

const auto _Fallback = [&] { return _STD _Print_newline_only_nonunicode(_Ostr); };

return _STD _Do_on_maybe_unicode_console(_Ostr, _Unicode_console, _Fallback);
}

template <int = 0>
void _Vprint_unicode_impl(
const _Add_newline _Add_nl, ostream& _Ostr, const string_view _Fmt_str, const format_args _Fmt_args) {
Expand Down Expand Up @@ -258,7 +299,20 @@ void println(ostream& _Ostr, const format_string<_Types...> _Fmt, _Types&&... _A

_EXPORT_STD template <int = 0> // improves throughput, see GH-2329
void println(ostream& _Ostr) {
_STD print(_Ostr, "\n");
const ostream::sentry _Ok(_Ostr);
ios_base::iostate _State = ios_base::goodbit;

if (!_Ok) [[unlikely]] {
_State |= ios_base::badbit;
} else [[likely]] {
if constexpr (_STD _Is_ordinary_literal_encoding_utf8()) {
_State |= _STD _Print_newline_only_unicode(_Ostr);
} else {
_State |= _STD _Print_newline_only_nonunicode(_Ostr);
}
}

_Ostr.setstate(_State);
}

_EXPORT_STD template <int = 0> // improves throughput, see GH-2329
Expand Down
32 changes: 31 additions & 1 deletion stl/inc/print
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,32 @@ inline void _Vprint_unicode_noformat_impl(FILE* const _Stream, const string_view
_STD _Do_on_maybe_unicode_console(_Stream, _Unicode_console, _Fallback);
}

inline void _Fputc_newline(FILE* const _Stream) {
const bool _Was_write_successful = _CSTD fputc('\n', _Stream) == '\n';

if (!_Was_write_successful) [[unlikely]] {
_Throw_system_error(static_cast<errc>(errno));
}
}

inline void _Print_newline_only_unicode(FILE* const _Stream) {
const auto _Unicode_console = [&](const __std_unicode_console_handle _Console_handle) {
const bool _Was_flush_successful = _CSTD fflush(_Stream) == 0;
if (!_Was_flush_successful) [[unlikely]] {
_Throw_system_error(static_cast<errc>(errno));
}

const __std_win_error _Console_print_result = __std_print_newline_only_to_unicode_console(_Console_handle);
if (_Console_print_result != __std_win_error::_Success) [[unlikely]] {
_STD _Throw_system_error_from_std_win_error(_Console_print_result);
}
};

const auto _Fallback = [&] { _STD _Fputc_newline(_Stream); };

_STD _Do_on_maybe_unicode_console(_Stream, _Unicode_console, _Fallback);
}

// Format to intermediate string buffer, then print to unicode console/file
inline void _Vprint_unicode_buffered_impl(
const _Add_newline _Add_nl, FILE* const _Stream, const string_view _Fmt_str, const format_args _Fmt_args) {
Expand Down Expand Up @@ -271,7 +297,11 @@ void println(FILE* const _Stream, const format_string<_Types...> _Fmt, _Types&&.

_EXPORT_STD template <int = 0> // improves throughput, see GH-2329
void println(FILE* _Stream) {
_STD print(_Stream, "\n");
if constexpr (_STD _Is_ordinary_literal_encoding_utf8()) {
_STD _Print_newline_only_unicode(_Stream);
} else {
_STD _Fputc_newline(_Stream);
}
}

_EXPORT_STD template <int = 0> // improves throughput, see GH-2329
Expand Down
18 changes: 18 additions & 0 deletions stl/src/print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,4 +297,22 @@ extern "C" {
}
}

[[nodiscard]] _Success_(return == __std_win_error::_Success) __std_win_error
__stdcall __std_print_newline_only_to_unicode_console(
_In_ const __std_unicode_console_handle _Console_handle) noexcept {
if (_Console_handle == __std_unicode_console_handle::_Invalid) [[unlikely]] {
return __std_win_error::_Invalid_parameter;
}

const auto _Actual_console_handle = reinterpret_cast<HANDLE>(_Console_handle);

const BOOL _Write_result = WriteConsoleW(_Actual_console_handle, L"\n", 1, nullptr, nullptr);

if (!_Write_result) [[unlikely]] {
return static_cast<__std_win_error>(GetLastError());
}

return __std_win_error::_Success;
}

} // extern "C"