123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510 |
- #ifndef _LIBCPP_SYNCSTREAM
- #define _LIBCPP_SYNCSTREAM
- #include <__config>
- #include <__utility/move.h>
- #include <iosfwd> // required for declaration of default arguments
- #include <string>
- #ifndef _LIBCPP_HAS_NO_THREADS
- # include <map>
- # include <mutex>
- # include <shared_mutex>
- #endif
- #include <ostream>
- #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
- # pragma GCC system_header
- #endif
- _LIBCPP_PUSH_MACROS
- #include <__undef_macros>
- _LIBCPP_BEGIN_NAMESPACE_STD
- #if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)
- # ifndef _LIBCPP_HAS_NO_THREADS
- class __wrapped_streambuf_mutex {
- _LIBCPP_HIDE_FROM_ABI __wrapped_streambuf_mutex() = default;
- public:
- __wrapped_streambuf_mutex(const __wrapped_streambuf_mutex&) = delete;
- __wrapped_streambuf_mutex& operator=(const __wrapped_streambuf_mutex&) = delete;
- _LIBCPP_HIDE_FROM_ABI void __inc_reference([[maybe_unused]] void* __ptr) {
- _LIBCPP_ASSERT_INTERNAL(__ptr != nullptr, "non-wrapped streambufs are never written to");
- unique_lock __lock{__mutex_};
- ++__lut_[reinterpret_cast<uintptr_t>(__ptr)].__count;
- }
-
- _LIBCPP_HIDE_FROM_ABI void __dec_reference([[maybe_unused]] void* __ptr) noexcept {
- unique_lock __lock{__mutex_};
- auto __it = __get_it(__ptr);
- if (__it->second.__count == 1)
- __lut_.erase(__it);
- else
- --__it->second.__count;
- }
-
-
-
-
-
-
-
-
-
- [[nodiscard]] _LIBCPP_HIDE_FROM_ABI lock_guard<mutex> __get_lock([[maybe_unused]] void* __ptr) noexcept {
- shared_lock __lock{__mutex_};
- return lock_guard{__get_it(__ptr)->second.__mutex};
- }
-
-
-
- [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __get_count([[maybe_unused]] void* __ptr) noexcept {
- _LIBCPP_ASSERT_INTERNAL(__ptr != nullptr, "non-wrapped streambufs are never written to");
- shared_lock __lock{__mutex_};
- auto __it = __lut_.find(reinterpret_cast<uintptr_t>(__ptr));
- return __it != __lut_.end() ? __it->second.__count : 0;
- }
- [[nodiscard]] static _LIBCPP_HIDE_FROM_ABI __wrapped_streambuf_mutex& __instance() noexcept {
- static __wrapped_streambuf_mutex __result;
- return __result;
- }
- private:
- struct __value {
- mutex __mutex;
- size_t __count{0};
- };
- shared_mutex __mutex_;
- map<uintptr_t, __value> __lut_;
- [[nodiscard]] _LIBCPP_HIDE_FROM_ABI map<uintptr_t, __value>::iterator __get_it(void* __ptr) noexcept {
- _LIBCPP_ASSERT_INTERNAL(__ptr != nullptr, "non-wrapped streambufs are never written to");
- auto __it = __lut_.find(reinterpret_cast<uintptr_t>(__ptr));
- _LIBCPP_ASSERT_INTERNAL(__it != __lut_.end(), "using a wrapped streambuf that has not been registered");
- _LIBCPP_ASSERT_INTERNAL(__it->second.__count >= 1, "found an inactive streambuf wrapper");
- return __it;
- }
- };
- # endif
- template <class _CharT, class _Traits, class _Allocator>
- class _LIBCPP_TEMPLATE_VIS basic_syncbuf : public basic_streambuf<_CharT, _Traits> {
- public:
- using char_type = _CharT;
- using traits_type = _Traits;
- using int_type = typename traits_type::int_type;
- using pos_type = typename traits_type::pos_type;
- using off_type = typename traits_type::off_type;
- using allocator_type = _Allocator;
- using streambuf_type = basic_streambuf<_CharT, _Traits>;
-
- _LIBCPP_HIDE_FROM_ABI explicit basic_syncbuf(streambuf_type* __obuf = nullptr)
- : basic_syncbuf(__obuf, _Allocator()) {}
- _LIBCPP_HIDE_FROM_ABI basic_syncbuf(streambuf_type* __obuf, _Allocator const& __alloc)
- : __wrapped_(__obuf), __str_(__alloc) {
- __inc_reference();
- }
- _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_) {
- __move_common(__other);
- }
- _LIBCPP_HIDE_FROM_ABI ~basic_syncbuf() {
- # ifndef _LIBCPP_HAS_NO_EXCEPTIONS
- try {
- # endif
- emit();
- # ifndef _LIBCPP_HAS_NO_EXCEPTIONS
- } catch (...) {
- }
- # endif
- __dec_reference();
- }
-
- _LIBCPP_HIDE_FROM_ABI basic_syncbuf& operator=(basic_syncbuf&& __other) {
-
-
- emit();
- __dec_reference();
- __wrapped_ = __other.get_wrapped();
- __str_ = std::move(__other.__str_);
- __emit_on_sync_ = __other.__emit_on_sync_;
- __move_common(__other);
- return *this;
- }
- _LIBCPP_HIDE_FROM_ABI void swap(basic_syncbuf& __other) {
- _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
- allocator_traits<_Allocator>::propagate_on_container_swap::value || get_allocator() == __other.get_allocator(),
- "violates the mandated swap precondition");
- basic_syncbuf __tmp(std::move(__other));
- __other = std::move(*this);
- *this = std::move(__tmp);
- }
-
- _LIBCPP_HIDE_FROM_ABI bool emit() { return emit(false); }
- _LIBCPP_HIDE_FROM_ABI streambuf_type* get_wrapped() const noexcept { return __wrapped_; }
- _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; }
- protected:
-
- _LIBCPP_HIDE_FROM_ABI_VIRTUAL
- int sync() override {
- if (__emit_on_sync_ && !emit(true))
- return -1;
- return 0;
- }
- _LIBCPP_HIDE_FROM_ABI_VIRTUAL
- int_type overflow(int_type __c = traits_type::eof()) override {
- if (traits_type::eq_int_type(__c, traits_type::eof()))
- return traits_type::not_eof(__c);
- if (this->pptr() == this->epptr()) {
- # ifndef _LIBCPP_HAS_NO_EXCEPTIONS
- try {
- # endif
- size_t __size = __str_.size();
- __str_.resize(__str_.capacity() + 1);
- _LIBCPP_ASSERT_INTERNAL(__str_.size() > __size, "the buffer hasn't grown");
- char_type* __p = static_cast<char_type*>(__str_.data());
- this->setp(__p, __p + __str_.size());
- this->pbump(__size);
- # ifndef _LIBCPP_HAS_NO_EXCEPTIONS
- } catch (...) {
- return traits_type::eof();
- }
- # endif
- }
- return this->sputc(traits_type::to_char_type(__c));
- }
- private:
- streambuf_type* __wrapped_;
-
-
-
-
- basic_string<_CharT, _Traits, _Allocator> __str_;
- bool __emit_on_sync_{false};
- _LIBCPP_HIDE_FROM_ABI bool emit(bool __flush) {
- if (!__wrapped_)
- return false;
- # ifndef _LIBCPP_HAS_NO_THREADS
- lock_guard<mutex> __lock = __wrapped_streambuf_mutex::__instance().__get_lock(__wrapped_);
- # endif
- bool __result = true;
- if (this->pptr() != this->pbase()) {
- _LIBCPP_ASSERT_INTERNAL(this->pbase() && this->pptr() && this->epptr(), "all put area pointers shold be valid");
-
-
- __result &= (__wrapped_->sputn(this->pbase(), this->pptr() - this->pbase()) != -1);
-
-
- this->setp(this->pbase(), this->epptr());
- }
- if (__flush)
- __result &= (__wrapped_->pubsync() != -1);
- return __result;
- }
- _LIBCPP_HIDE_FROM_ABI void __move_common(basic_syncbuf& __other) {
-
- char_type* __p = static_cast<char_type*>(__str_.data());
- this->setp(__p, __p + __str_.size());
- this->pbump(__other.pptr() - __other.pbase());
-
- __other.setp(nullptr, nullptr);
- __other.__wrapped_ = nullptr;
- }
- _LIBCPP_HIDE_FROM_ABI void __inc_reference() {
- # ifndef _LIBCPP_HAS_NO_THREADS
- if (__wrapped_)
- __wrapped_streambuf_mutex::__instance().__inc_reference(__wrapped_);
- # endif
- }
- _LIBCPP_HIDE_FROM_ABI void __dec_reference() noexcept {
- # ifndef _LIBCPP_HAS_NO_THREADS
- if (__wrapped_)
- __wrapped_streambuf_mutex::__instance().__dec_reference(__wrapped_);
- # endif
- }
- };
- using std::syncbuf;
- # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
- using std::wsyncbuf;
- # endif
- template <class _CharT, class _Traits, class _Allocator>
- _LIBCPP_HIDE_FROM_ABI void
- swap(basic_syncbuf<_CharT, _Traits, _Allocator>& __lhs, basic_syncbuf<_CharT, _Traits, _Allocator>& __rhs) {
- __lhs.swap(__rhs);
- }
- template <class _CharT, class _Traits, class _Allocator>
- class _LIBCPP_TEMPLATE_VIS basic_osyncstream : public basic_ostream<_CharT, _Traits> {
- public:
- using char_type = _CharT;
- using traits_type = _Traits;
- using int_type = typename traits_type::int_type;
- using pos_type = typename traits_type::pos_type;
- using off_type = typename traits_type::off_type;
- using allocator_type = _Allocator;
- using streambuf_type = basic_streambuf<char_type, traits_type>;
- using syncbuf_type = basic_syncbuf<char_type, traits_type, allocator_type>;
-
- _LIBCPP_HIDE_FROM_ABI basic_osyncstream(streambuf_type* __obuf, allocator_type const& __alloc)
- : basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__obuf, __alloc) {}
- _LIBCPP_HIDE_FROM_ABI explicit basic_osyncstream(streambuf_type* __obuf)
- : basic_osyncstream(__obuf, allocator_type()) {}
- _LIBCPP_HIDE_FROM_ABI basic_osyncstream(basic_ostream<char_type, traits_type>& __os, allocator_type const& __alloc)
- : basic_osyncstream(__os.rdbuf(), __alloc) {}
- _LIBCPP_HIDE_FROM_ABI explicit basic_osyncstream(basic_ostream<char_type, traits_type>& __os)
- : basic_osyncstream(__os, allocator_type()) {}
- _LIBCPP_HIDE_FROM_ABI basic_osyncstream(basic_osyncstream&& __other) noexcept
- : basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(std::move(__other.__sb_)) {
- this->set_rdbuf(std::addressof(__sb_));
- }
-
- _LIBCPP_HIDE_FROM_ABI basic_osyncstream& operator=(basic_osyncstream&& __other) = default;
-
- _LIBCPP_HIDE_FROM_ABI void emit() {
-
-
-
-
- typename basic_ostream<char_type, traits_type>::sentry __s(*this);
- if (__s) {
- # ifndef _LIBCPP_HAS_NO_EXCEPTIONS
- try {
- # endif
- if (__sb_.emit() == false)
- this->setstate(ios::badbit);
- # ifndef _LIBCPP_HAS_NO_EXCEPTIONS
- } catch (...) {
- this->__set_badbit_and_consider_rethrow();
- }
- # endif
- }
- }
- _LIBCPP_HIDE_FROM_ABI streambuf_type* get_wrapped() const noexcept { return __sb_.get_wrapped(); }
- _LIBCPP_HIDE_FROM_ABI syncbuf_type* rdbuf() const noexcept {
- return const_cast<syncbuf_type*>(std::addressof(__sb_));
- }
- private:
- syncbuf_type __sb_;
- };
- using std::osyncstream;
- # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
- using std::wosyncstream;
- # endif
- #endif
- _LIBCPP_END_NAMESPACE_STD
- _LIBCPP_POP_MACROS
- #endif
|