1// <syncstream> -*- C++ -*-
 
    3// Copyright (C) 2020-2021 Free Software Foundation, Inc.
 
    5// This file is part of the GNU ISO C++ Library.  This library is free
 
    6// software; you can redistribute it and/or modify it under the
 
    7// terms of the GNU General Public License as published by the
 
    8// Free Software Foundation; either version 3, or (at your option)
 
   11// This library is distributed in the hope that it will be useful,
 
   12// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
   13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
   14// GNU General Public License for more details.
 
   16// Under Section 7 of GPL version 3, you are granted additional
 
   17// permissions described in the GCC Runtime Library Exception, version
 
   18// 3.1, as published by the Free Software Foundation.
 
   20// You should have received a copy of the GNU General Public License and
 
   21// a copy of the GCC Runtime Library Exception along with this program;
 
   22// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
   23// <http://www.gnu.org/licenses/>.
 
   25/** @file include/syncstream
 
   26 *  This is a Standard C++ Library header.
 
   29#ifndef _GLIBCXX_SYNCSTREAM
 
   30#define _GLIBCXX_SYNCSTREAM 1
 
   32#if __cplusplus > 201703L
 
   34#include <bits/c++config.h>
 
   35#if _GLIBCXX_USE_CXX11_ABI
 
   37#define __cpp_lib_syncbuf 201803L
 
   39#pragma GCC system_header
 
   43#include <bits/alloc_traits.h>
 
   44#include <bits/allocator.h>
 
   45#include <bits/functexcept.h>
 
   46#include <bits/functional_hash.h>
 
   47#include <bits/std_mutex.h>
 
   49namespace std _GLIBCXX_VISIBILITY(default)
 
   51_GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   53  template<typename _CharT, typename _Traits, typename _Alloc>
 
   54    class basic_syncbuf : public __syncbuf_base<_CharT, _Traits>
 
   57      using char_type = _CharT;
 
   58      using int_type = typename _Traits::int_type;
 
   59      using pos_type = typename _Traits::pos_type;
 
   60      using off_type = typename _Traits::off_type;
 
   61      using traits_type = _Traits;
 
   62      using allocator_type = _Alloc;
 
   63      using streambuf_type = basic_streambuf<_CharT, _Traits>;
 
   66      : basic_syncbuf(nullptr, allocator_type{})
 
   70      basic_syncbuf(streambuf_type* __obuf)
 
   71      : basic_syncbuf(__obuf, allocator_type{})
 
   74      basic_syncbuf(streambuf_type* __obuf, const allocator_type& __alloc)
 
   75      : __syncbuf_base<_CharT, _Traits>(__obuf)
 
   80      basic_syncbuf(basic_syncbuf&& __other)
 
   81      : __syncbuf_base<_CharT, _Traits>(__other._M_wrapped)
 
   82      , _M_impl(std::move(__other._M_impl))
 
   83      , _M_mtx(std::move(__other._M_mtx))
 
   85        this->_M_emit_on_sync = __other._M_emit_on_sync;
 
   86        this->_M_needs_sync = __other._M_needs_sync;
 
   87        __other._M_wrapped = nullptr;
 
  101      operator=(basic_syncbuf&& __other)
 
  105        _M_impl = std::move(__other._M_impl);
 
  106        this->_M_emit_on_sync = __other._M_emit_on_sync;
 
  107        this->_M_needs_sync = __other._M_needs_sync;
 
  108        this->_M_wrapped = __other._M_wrapped;
 
  109        __other._M_wrapped = nullptr;
 
  110        _M_mtx = std::move(__other._M_mtx);
 
  116      swap(basic_syncbuf& __other)
 
  118        using _ATr = allocator_traits<_Alloc>;
 
  119        if constexpr (!_ATr::propagate_on_container_swap::value)
 
  120          __glibcxx_assert(get_allocator() == __other.get_allocator());
 
  122        std::swap(_M_impl, __other._M_impl);
 
  123        std::swap(this->_M_emit_on_sync, __other._M_emit_on_sync);
 
  124        std::swap(this->_M_needs_sync, __other._M_needs_sync);
 
  125        std::swap(this->_M_wrapped, __other._M_wrapped);
 
  126        std::swap(_M_mtx, __other._M_mtx);
 
  132        if (!this->_M_wrapped)
 
  135        auto __s = std::move(_M_impl).str();
 
  137        const lock_guard<__mutex> __l(_M_mtx);
 
  138        if (auto __size = __s.size())
 
  140            auto __n = this->_M_wrapped->sputn(__s.data(), __size);
 
  144                _M_impl.str(std::move(__s));
 
  149        if (this->_M_needs_sync)
 
  151            this->_M_needs_sync = false;
 
  152            if (this->_M_wrapped->pubsync() != 0)
 
  159      get_wrapped() const noexcept
 
  160      { return this->_M_wrapped; }
 
  163      get_allocator() const noexcept
 
  164      { return _M_impl.get_allocator(); }
 
  167      set_emit_on_sync(bool __b) noexcept
 
  168      { this->_M_emit_on_sync = __b; }
 
  174        this->_M_needs_sync = true;
 
  175        if (this->_M_emit_on_sync && !emit())
 
  181      overflow(int_type __c) override
 
  183        int_type __eof = traits_type::eof();
 
  184        if (__builtin_expect(!traits_type::eq_int_type(__c, __eof), true))
 
  185          return _M_impl.sputc(__c);
 
  190      xsputn(const char_type* __s, streamsize __n) override
 
  191      { return _M_impl.sputn(__s, __n); }
 
  194      basic_stringbuf<char_type, traits_type, allocator_type> _M_impl;
 
  198#if _GLIBCXX_HAS_GTHREADS
 
  202          : _M_mtx(__t ? &_S_get_mutex(__t) : nullptr)
 
  206        swap(__mutex& __other) noexcept
 
  207        { std::swap(_M_mtx, __other._M_mtx); }
 
  221        // FIXME: This should be put in the .so
 
  223        _S_get_mutex(void* __t)
 
  225          const unsigned char __mask = 0xf;
 
  226          static mutex __m[__mask + 1];
 
  228          auto __key = _Hash_impl::hash(__t) & __mask;
 
  233        void swap(__mutex&&) noexcept { }
 
  237        __mutex(__mutex&&) = default;
 
  238        __mutex& operator=(__mutex&&) = default;
 
  243  template <typename _CharT, typename _Traits, typename _Alloc>
 
  244    class basic_osyncstream : public basic_ostream<_CharT, _Traits>
 
  246      using __ostream_type = basic_ostream<_CharT, _Traits>;
 
  250      using char_type = _CharT;
 
  251      using traits_type = _Traits;
 
  252      using allocator_type = _Alloc;
 
  253      using int_type = typename traits_type::int_type;
 
  254      using pos_type = typename traits_type::pos_type;
 
  255      using off_type = typename traits_type::off_type;
 
  256      using syncbuf_type = basic_syncbuf<_CharT, _Traits, _Alloc>;
 
  257      using streambuf_type = typename syncbuf_type::streambuf_type;
 
  260      syncbuf_type _M_syncbuf;
 
  263      basic_osyncstream(streambuf_type* __buf, const allocator_type& __a)
 
  264        : _M_syncbuf(__buf, __a)
 
  265      { this->init(std::__addressof(_M_syncbuf)); }
 
  267      explicit basic_osyncstream(streambuf_type* __buf)
 
  269      { this->init(std::__addressof(_M_syncbuf)); }
 
  271      basic_osyncstream(basic_ostream<char_type, traits_type>& __os,
 
  272                        const allocator_type& __a)
 
  273        : basic_osyncstream(__os.rdbuf(), __a)
 
  274      { this->init(std::__addressof(_M_syncbuf)); }
 
  276      explicit basic_osyncstream(basic_ostream<char_type, traits_type>& __os)
 
  277        : basic_osyncstream(__os.rdbuf())
 
  278      { this->init(std::__addressof(_M_syncbuf)); }
 
  280      basic_osyncstream(basic_osyncstream&& __rhs) noexcept
 
  281        : __ostream_type(std::move(__rhs)),
 
  282        _M_syncbuf(std::move(__rhs._M_syncbuf))
 
  283      { __ostream_type::set_rdbuf(std::__addressof(_M_syncbuf)); }
 
  285      ~basic_osyncstream() = default;
 
  287      basic_osyncstream& operator=(basic_osyncstream&&) noexcept = default;
 
  289      syncbuf_type* rdbuf() const noexcept
 
  290      { return const_cast<syncbuf_type*>(&_M_syncbuf); }
 
  292      streambuf_type* get_wrapped() const noexcept
 
  293      { return _M_syncbuf.get_wrapped(); }
 
  297        if (!_M_syncbuf.emit())
 
  298          this->setstate(ios_base::failbit);
 
  302  template <class _CharT, class _Traits, class _Allocator>
 
  304    swap(basic_syncbuf<_CharT, _Traits, _Allocator>& __x,
 
  305         basic_syncbuf<_CharT, _Traits, _Allocator>& __y) noexcept
 
  308  using syncbuf = basic_syncbuf<char>;
 
  309  using wsyncbuf = basic_syncbuf<wchar_t>;
 
  311  using osyncstream = basic_osyncstream<char>;
 
  312  using wosyncstream = basic_osyncstream<wchar_t>;
 
  313_GLIBCXX_END_NAMESPACE_VERSION
 
  315#endif // _GLIBCXX_USE_CXX11_ABI
 
  317#endif  /* _GLIBCXX_SYNCSTREAM */