Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/c++/15/syncstream
1 // <syncstream> -*- C++ -*- 2 3 // Copyright (C) 2020-2025 Free Software Foundation, Inc. 4 // 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) 9 // any later version. 10 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. 15 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. 19 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/>. 24 25 /** @file include/syncstream 26 * This is a Standard C++ Library header. 27 */ 28 29 #ifndef _GLIBCXX_SYNCSTREAM 30 #define _GLIBCXX_SYNCSTREAM 1 31 32 #ifdef _GLIBCXX_SYSHDR 33 #pragma GCC system_header 34 #endif 35 36 #include <bits/requires_hosted.h> // iostreams 37 38 #include <bits/c++config.h> 39 40 #define __glibcxx_want_syncbuf 41 #include <bits/version.h> 42 43 #ifdef __cpp_lib_syncbuf // C++ >= 20 && HOSTED && CXX11ABI 44 #include <sstream> 45 46 #include <bits/alloc_traits.h> 47 #include <bits/allocator.h> 48 #include <bits/functexcept.h> 49 #include <bits/functional_hash.h> 50 #include <bits/std_mutex.h> 51 52 namespace std _GLIBCXX_VISIBILITY(default) 53 { 54 _GLIBCXX_BEGIN_NAMESPACE_VERSION 55 56 template<typename _CharT, typename _Traits, typename _Alloc> 57 class basic_syncbuf : public __syncbuf_base<_CharT, _Traits> 58 { 59 public: 60 using char_type = _CharT; 61 using int_type = typename _Traits::int_type; 62 using pos_type = typename _Traits::pos_type; 63 using off_type = typename _Traits::off_type; 64 using traits_type = _Traits; 65 using allocator_type = _Alloc; 66 using streambuf_type = basic_streambuf<_CharT, _Traits>; 67 68 basic_syncbuf() 69 : basic_syncbuf(nullptr, allocator_type{}) 70 { } 71 72 explicit 73 basic_syncbuf(streambuf_type* __obuf) 74 : basic_syncbuf(__obuf, allocator_type{}) 75 { } 76 77 basic_syncbuf(streambuf_type* __obuf, const allocator_type& __alloc) 78 : __syncbuf_base<_CharT, _Traits>(__obuf) 79 , _M_impl(__alloc) 80 , _M_mtx(__obuf) 81 { } 82 83 basic_syncbuf(basic_syncbuf&& __other) 84 : __syncbuf_base<_CharT, _Traits>(__other._M_wrapped) 85 , _M_impl(std::move(__other._M_impl)) 86 , _M_mtx(std::move(__other._M_mtx)) 87 { 88 this->_M_emit_on_sync = __other._M_emit_on_sync; 89 this->_M_needs_sync = __other._M_needs_sync; 90 __other._M_wrapped = nullptr; 91 } 92 93 ~basic_syncbuf() 94 { 95 __try 96 { 97 emit(); 98 } 99 __catch (...) 100 { } 101 } 102 103 basic_syncbuf& 104 operator=(basic_syncbuf&& __other) 105 { 106 emit(); 107 108 _M_impl = std::move(__other._M_impl); 109 this->_M_emit_on_sync = __other._M_emit_on_sync; 110 this->_M_needs_sync = __other._M_needs_sync; 111 this->_M_wrapped = __other._M_wrapped; 112 __other._M_wrapped = nullptr; 113 _M_mtx = std::move(__other._M_mtx); 114 115 return *this; 116 } 117 118 void 119 swap(basic_syncbuf& __other) 120 { 121 using _ATr = allocator_traits<_Alloc>; 122 if constexpr (!_ATr::propagate_on_container_swap::value) 123 __glibcxx_assert(get_allocator() == __other.get_allocator()); 124 125 std::swap(_M_impl, __other._M_impl); 126 std::swap(this->_M_emit_on_sync, __other._M_emit_on_sync); 127 std::swap(this->_M_needs_sync, __other._M_needs_sync); 128 std::swap(this->_M_wrapped, __other._M_wrapped); 129 std::swap(_M_mtx, __other._M_mtx); 130 } 131 132 bool 133 emit() 134 { 135 if (!this->_M_wrapped) 136 return false; 137 138 auto __s = std::move(_M_impl).str(); 139 140 const lock_guard<__mutex> __l(_M_mtx); 141 if (auto __size = __s.size()) 142 { 143 auto __n = this->_M_wrapped->sputn(__s.data(), __size); 144 if (__n != __size) 145 { 146 __s.erase(0, __n); 147 _M_impl.str(std::move(__s)); 148 return false; 149 } 150 } 151 152 if (this->_M_needs_sync) 153 { 154 this->_M_needs_sync = false; 155 if (this->_M_wrapped->pubsync() != 0) 156 return false; 157 } 158 return true; 159 } 160 161 streambuf_type* 162 get_wrapped() const noexcept 163 { return this->_M_wrapped; } 164 165 allocator_type 166 get_allocator() const noexcept 167 { return _M_impl.get_allocator(); } 168 169 void 170 set_emit_on_sync(bool __b) noexcept 171 { this->_M_emit_on_sync = __b; } 172 173 protected: 174 int 175 sync() override 176 { 177 this->_M_needs_sync = true; 178 if (this->_M_emit_on_sync && !emit()) 179 return -1; 180 return 0; 181 } 182 183 int_type 184 overflow(int_type __c) override 185 { 186 int_type __eof = traits_type::eof(); 187 if (__builtin_expect(!traits_type::eq_int_type(__c, __eof), true)) 188 return _M_impl.sputc(__c); 189 return __eof; 190 } 191 192 streamsize 193 xsputn(const char_type* __s, streamsize __n) override 194 { return _M_impl.sputn(__s, __n); } 195 196 private: 197 basic_stringbuf<char_type, traits_type, allocator_type> _M_impl; 198 199 struct __mutex 200 { 201 #if _GLIBCXX_HAS_GTHREADS 202 mutex* _M_mtx; 203 204 __mutex(void* __t) 205 : _M_mtx(__t ? &_S_get_mutex(__t) : nullptr) 206 { } 207 208 void 209 swap(__mutex& __other) noexcept 210 { std::swap(_M_mtx, __other._M_mtx); } 211 212 void 213 lock() 214 { 215 _M_mtx->lock(); 216 } 217 218 void 219 unlock() 220 { 221 _M_mtx->unlock(); 222 } 223 224 // FIXME: This should be put in the .so 225 static mutex& 226 _S_get_mutex(void* __t) 227 { 228 const unsigned char __mask = 0xf; 229 static mutex __m[__mask + 1]; 230 231 auto __key = _Hash_impl::hash(__t) & __mask; 232 return __m[__key]; 233 } 234 #else 235 __mutex(void*) { } 236 void swap(__mutex&&) noexcept { } 237 void lock() { } 238 void unlock() { } 239 #endif 240 __mutex(__mutex&&) = default; 241 __mutex& operator=(__mutex&&) = default; 242 }; 243 __mutex _M_mtx; 244 }; 245 246 template <typename _CharT, typename _Traits, typename _Alloc> 247 class basic_osyncstream : public basic_ostream<_CharT, _Traits> 248 { 249 using __ostream_type = basic_ostream<_CharT, _Traits>; 250 251 public: 252 // Types: 253 using char_type = _CharT; 254 using traits_type = _Traits; 255 using allocator_type = _Alloc; 256 using int_type = typename traits_type::int_type; 257 using pos_type = typename traits_type::pos_type; 258 using off_type = typename traits_type::off_type; 259 using syncbuf_type = basic_syncbuf<_CharT, _Traits, _Alloc>; 260 using streambuf_type = typename syncbuf_type::streambuf_type; 261 262 private: 263 syncbuf_type _M_syncbuf; 264 265 public: 266 basic_osyncstream(streambuf_type* __buf, const allocator_type& __a) 267 : _M_syncbuf(__buf, __a) 268 { this->init(std::__addressof(_M_syncbuf)); } 269 270 explicit basic_osyncstream(streambuf_type* __buf) 271 : _M_syncbuf(__buf) 272 { this->init(std::__addressof(_M_syncbuf)); } 273 274 basic_osyncstream(basic_ostream<char_type, traits_type>& __os, 275 const allocator_type& __a) 276 : basic_osyncstream(__os.rdbuf(), __a) 277 { this->init(std::__addressof(_M_syncbuf)); } 278 279 explicit basic_osyncstream(basic_ostream<char_type, traits_type>& __os) 280 : basic_osyncstream(__os.rdbuf()) 281 { this->init(std::__addressof(_M_syncbuf)); } 282 283 basic_osyncstream(basic_osyncstream&& __rhs) noexcept 284 : __ostream_type(std::move(__rhs)), 285 _M_syncbuf(std::move(__rhs._M_syncbuf)) 286 { __ostream_type::set_rdbuf(std::__addressof(_M_syncbuf)); } 287 288 ~basic_osyncstream() = default; 289 290 basic_osyncstream& operator=(basic_osyncstream&&) = default; 291 292 syncbuf_type* rdbuf() const noexcept 293 { return const_cast<syncbuf_type*>(&_M_syncbuf); } 294 295 streambuf_type* get_wrapped() const noexcept 296 { return _M_syncbuf.get_wrapped(); } 297 298 void emit() 299 { 300 if (!_M_syncbuf.emit()) 301 this->setstate(ios_base::failbit); 302 } 303 }; 304 305 template <class _CharT, class _Traits, class _Allocator> 306 inline void 307 swap(basic_syncbuf<_CharT, _Traits, _Allocator>& __x, 308 basic_syncbuf<_CharT, _Traits, _Allocator>& __y) noexcept 309 { __x.swap(__y); } 310 311 using syncbuf = basic_syncbuf<char>; 312 using wsyncbuf = basic_syncbuf<wchar_t>; 313 314 using osyncstream = basic_osyncstream<char>; 315 using wosyncstream = basic_osyncstream<wchar_t>; 316 _GLIBCXX_END_NAMESPACE_VERSION 317 } // namespace std 318 #endif // __cpp_lib_syncbuf 319 320 #endif /* _GLIBCXX_SYNCSTREAM */