[libcxx-commits] [libcxx] [libc++] Implement p0753r2 Manipulators for C++ Synchronized Buffered Ostream (PR #97955)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jul 12 09:05:13 PDT 2024


================
@@ -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())) {
----------------
ldionne wrote:

I don't know how to implement this without either breaking the ABI (by inserting a `virtual bool __is_syncstream()` function to `basic_ostream`) or relying on `dynamic_cast`, as you do here. This is tricky though because when we don't have RTTI enabled, we can't implement this properly.

I see a few options:
1. Do what you do here. This is simple, but if a user compiles with `-fno-rtti`, they get the wrong behavior.
2. Try to move the `dynamic_cast` to the dylib, where we compile with RTTI all the time (well unless the vendor decides to disable RTTI, in which case they would get the wrong behavior but that's probably OK). This is what we do in `ostream.cpp` for `std::print`: https://github.com/llvm/llvm-project/blob/026566a5a8bf5223e3f58ed9d80e7f3d5886decf/libcxx/src/ostream.cpp#L19

I am not sure whether it's possible to move the `dynamic_cast` to the dylib in all cases, since we'd have to get rid of the `CharT` and `Traits` template parameter dependency. We could at least do it for `char` and `wchar_t`, maybe. I am not certain yet what approach is the best, but I think this is worth giving some thought and trying a few things to see what's possible.

https://github.com/llvm/llvm-project/pull/97955


More information about the libcxx-commits mailing list