[libcxx-commits] [libcxx] [libc++] Implement p0753r2 Manipulators for C++ Synchronized Buffered Ostream (PR #97955)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Jul 7 07:57:12 PDT 2024
https://github.com/huixie90 created https://github.com/llvm/llvm-project/pull/97955
None
>From e027c7fdd32cbfdd1d8a990490c1e6fe2c5c924b Mon Sep 17 00:00:00 2001
From: Hui <hui.xie0621 at gmail.com>
Date: Sun, 7 Jul 2024 15:56:49 +0100
Subject: [PATCH] [libc++] Implement p0753r2 Manipulators for C++ Synchronized
Buffered Ostream
---
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/__ostream/syncbuf_base.h | 92 +++++++++++++++++++++++++
libcxx/include/module.modulemap | 4 ++
libcxx/include/ostream | 10 +++
libcxx/include/syncstream | 20 +++---
5 files changed, 119 insertions(+), 8 deletions(-)
create mode 100644 libcxx/include/__ostream/syncbuf_base.h
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 8d0ffd6ed725bd..9cc96730923b86 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -575,6 +575,7 @@ set(files
__numeric/transform_reduce.h
__ostream/basic_ostream.h
__ostream/print.h
+ __ostream/syncbuf_base.h
__pstl/backend.h
__pstl/backend_fwd.h
__pstl/backends/default.h
diff --git a/libcxx/include/__ostream/syncbuf_base.h b/libcxx/include/__ostream/syncbuf_base.h
new file mode 100644
index 00000000000000..fb49f94bc5704c
--- /dev/null
+++ b/libcxx/include/__ostream/syncbuf_base.h
@@ -0,0 +1,92 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___OSTREAM_SYNCBUF_BASE_H
+#define _LIBCPP___OSTREAM_SYNCBUF_BASE_H
+
+#include <__config>
+#include <__ostream/basic_ostream.h>
+#include <streambuf>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)
+
+template <class _CharT, class _Traits>
+class _LIBCPP_TEMPLATE_VIS __syncbuf_base : public basic_streambuf<_CharT, _Traits> {
+public:
+
+protected:
+ _LIBCPP_HIDE_FROM_ABI explicit __syncbuf_base(bool __b = false) : __emit_on_sync_(__b) {}
+
+private:
+ bool __emit_on_sync_{false};
+
+ virtual bool __emit() = 0;
+
+ template <class, class, class>
+ friend class basic_syncbuf;
+
+ friend struct __syncbuf_base_access;
+};
+
+struct __syncbuf_base_access {
+ template <class _CharT, class _Traits>
+ _LIBCPP_HIDE_FROM_ABI static void __set_emit_on_sync(__syncbuf_base<_CharT, _Traits>* __buf, bool __b) {
+ __buf->__emit_on_sync_ = __b;
+ }
+
+ template <class _CharT, class _Traits>
+ _LIBCPP_HIDE_FROM_ABI static bool __emit(__syncbuf_base<_CharT, _Traits>* __buf) {
+ return __buf->__emit();
+ }
+};
+
+template <class _CharT, class _Traits>
+_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& emit_on_flush(basic_ostream<_CharT, _Traits>& __os) {
+ if (auto* __buf = dynamic_cast<__syncbuf_base<_CharT, _Traits>*>(__os.rdbuf())) {
+ __syncbuf_base_access::__set_emit_on_sync(__buf, true);
+ }
+ return __os;
+}
+
+template <class _CharT, class _Traits>
+_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& noemit_on_flush(basic_ostream<_CharT, _Traits>& __os) {
+ if (auto* __buf = dynamic_cast<__syncbuf_base<_CharT, _Traits>*>(__os.rdbuf())) {
+ __syncbuf_base_access::__set_emit_on_sync(__buf, false);
+ }
+ return __os;
+}
+
+template <class _CharT, class _Traits>
+_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& flush_emit(basic_ostream<_CharT, _Traits>& __os) {
+ __os.flush();
+ if (auto* __buf = dynamic_cast<__syncbuf_base<_CharT, _Traits>*>(__os.rdbuf())) {
+ // The standard specifies that:
+ // After constructing a sentry object, calls buf->emit().
+ // If that call returns false, calls os.setstate(ios_base::badbit).
+ //
+ // syncstream::emit already constructs a sentry
+ bool __emit_result = __syncbuf_base_access::__emit(__buf);
+ if (!__emit_result) {
+ __os.setstate(ios_base::badbit);
+ }
+ }
+ return __os;
+}
+
+#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___OSTREAM_SYNCBUF_BASE_H
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index 9ffccf66ff0948..4b9921833c5117 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -1631,6 +1631,10 @@ module std_private_ostream_print [system] {
export std_print
}
+module std_private_ostream_syncbuf_base [system] {
+ header "__ostream/syncbuf_base.h"
+}
+
module std_private_random_bernoulli_distribution [system] { header "__random/bernoulli_distribution.h" }
module std_private_random_binomial_distribution [system] { header "__random/binomial_distribution.h" }
module std_private_random_cauchy_distribution [system] { header "__random/cauchy_distribution.h" }
diff --git a/libcxx/include/ostream b/libcxx/include/ostream
index f75110e7d73f79..afb1a8b2f39c0b 100644
--- a/libcxx/include/ostream
+++ b/libcxx/include/ostream
@@ -126,6 +126,15 @@ template <class charT, class traits>
template <class charT, class traits>
basic_ostream<charT,traits>& flush(basic_ostream<charT,traits>& os);
+template<class charT, class traits>
+ basic_ostream<charT, traits>& emit_on_flush(basic_ostream<charT, traits>& os); // since C++20
+
+template<class charT, class traits>
+ basic_ostream<charT, traits>& noemit_on_flush(basic_ostream<charT, traits>& os); // since C++20
+
+template<class charT, class traits>
+ basic_ostream<charT, traits>& flush_emit(basic_ostream<charT, traits>& os); // since C++20
+
// rvalue stream insertion
template <class Stream, class T>
Stream&& operator<<(Stream&& os, const T& x);
@@ -175,6 +184,7 @@ void vprint_nonunicode(ostream& os, string_view fmt, format_args args);
#include <__config>
#include <__ostream/basic_ostream.h>
#include <__ostream/print.h>
+#include <__ostream/syncbuf_base.h>
#include <version>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
diff --git a/libcxx/include/syncstream b/libcxx/include/syncstream
index e6f35b6f428eda..243d6a56a5dc9c 100644
--- a/libcxx/include/syncstream
+++ b/libcxx/include/syncstream
@@ -116,6 +116,7 @@ namespace std {
*/
#include <__config>
+#include <__ostream/syncbuf_base.h>
#include <__utility/move.h>
#include <ios>
#include <iosfwd> // required for declaration of default arguments
@@ -240,7 +241,7 @@ private:
// Therefore the allocator used in the constructor is passed to the
// basic_string. The class does not keep a copy of this allocator.
template <class _CharT, class _Traits, class _Allocator>
-class _LIBCPP_TEMPLATE_VIS basic_syncbuf : public basic_streambuf<_CharT, _Traits> {
+class _LIBCPP_TEMPLATE_VIS basic_syncbuf : public __syncbuf_base<_CharT, _Traits> {
public:
using char_type = _CharT;
using traits_type = _Traits;
@@ -262,7 +263,9 @@ public:
}
_LIBCPP_HIDE_FROM_ABI basic_syncbuf(basic_syncbuf&& __other)
- : __wrapped_(__other.get_wrapped()), __str_(std::move(__other.__str_)), __emit_on_sync_(__other.__emit_on_sync_) {
+ : __syncbuf_base<_CharT, _Traits>(__other.__emit_on_sync_),
+ __wrapped_(__other.get_wrapped()),
+ __str_(std::move(__other.__str_)) {
__move_common(__other);
}
@@ -286,9 +289,9 @@ public:
emit();
__dec_reference();
- __wrapped_ = __other.get_wrapped();
- __str_ = std::move(__other.__str_);
- __emit_on_sync_ = __other.__emit_on_sync_;
+ __wrapped_ = __other.get_wrapped();
+ __str_ = std::move(__other.__str_);
+ this->__emit_on_sync_ = __other.__emit_on_sync_;
__move_common(__other);
@@ -313,14 +316,14 @@ public:
_LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const noexcept { return __str_.get_allocator(); }
- _LIBCPP_HIDE_FROM_ABI void set_emit_on_sync(bool __b) noexcept { __emit_on_sync_ = __b; }
+ _LIBCPP_HIDE_FROM_ABI void set_emit_on_sync(bool __b) noexcept { this->__emit_on_sync_ = __b; }
protected:
// [syncstream.syncbuf.virtuals], overridden virtual functions
_LIBCPP_HIDE_FROM_ABI_VIRTUAL
int sync() override {
- if (__emit_on_sync_ && !emit(true))
+ if (this->__emit_on_sync_ && !emit(true))
return -1;
return 0;
}
@@ -361,7 +364,6 @@ private:
// the now deprecated get_temporary_buffer
basic_string<_CharT, _Traits, _Allocator> __str_;
- bool __emit_on_sync_{false};
_LIBCPP_HIDE_FROM_ABI bool emit(bool __flush) {
if (!__wrapped_)
@@ -389,6 +391,8 @@ private:
return __result;
}
+ _LIBCPP_HIDE_FROM_ABI_VIRTUAL bool __emit() override { return emit(); }
+
_LIBCPP_HIDE_FROM_ABI void __move_common(basic_syncbuf& __other) {
// Adjust the put area pointers to our buffer.
char_type* __p = static_cast<char_type*>(__str_.data());
More information about the libcxx-commits
mailing list