Line data Source code
1 : // The libMesh Finite Element Library. 2 : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 : 4 : // This library is free software; you can redistribute it and/or 5 : // modify it under the terms of the GNU Lesser General Public 6 : // License as published by the Free Software Foundation; either 7 : // version 2.1 of the License, or (at your option) any later version. 8 : 9 : // This library is distributed in the hope that it will be useful, 10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 : // Lesser General Public License for more details. 13 : 14 : // You should have received a copy of the GNU Lesser General Public 15 : // License along with this library; if not, write to the Free Software 16 : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 : 18 : #ifndef LIBMESH_THREAD_BUFFERED_SYNCBUF_H 19 : #define LIBMESH_THREAD_BUFFERED_SYNCBUF_H 20 : 21 : #include <streambuf> 22 : #include <string> 23 : #include <memory> 24 : 25 : namespace libMesh 26 : { 27 : namespace Threads 28 : { 29 : class spin_mutex; 30 : } 31 : 32 2772 : class ThreadBufferedSyncbuf : public std::streambuf 33 : { 34 : public: 35 : explicit ThreadBufferedSyncbuf(std::streambuf & sink, bool flush_on_newline = true); 36 : 37 : /** 38 : * Defaulted destructor defined in implementation so we don't need to include threads.h 39 : */ 40 : ~ThreadBufferedSyncbuf(); 41 : 42 : protected: 43 : // Single-char path 44 : int_type overflow(int_type ch) override; 45 : 46 : // Bulk write path 47 : std::streamsize xsputn(const char * s, std::streamsize n) override; 48 : 49 : // Flush path (std::flush / std::endl / ostream::flush) 50 : int sync() override; 51 : 52 : private: 53 : /** 54 : * A class that wraps a thread-local string. We make sure when we're destructing and our buffer is 55 : * non-empty to write to our main output sink 56 : */ 57 : class ThreadLocalBuffer 58 : { 59 : public: 60 16578 : explicit ThreadLocalBuffer(ThreadBufferedSyncbuf & owner) : _owner(owner) {} 61 : 62 : /** 63 : * Ensures we write to our sink upon destruction if our buf is non-empty 64 : */ 65 : ~ThreadLocalBuffer(); 66 : 67 : /// per-thread buffer 68 : std::string buf; 69 : 70 : private: 71 : /// owning syncing stream buffer 72 : ThreadBufferedSyncbuf & _owner; 73 : }; 74 : 75 : /** 76 : * One ThreadLocalBuffer instance per thread, constructed on first use with *this. 77 : */ 78 : ThreadLocalBuffer & thread_local_buffer(); 79 : 80 : /** 81 : * Emit from the thread local buffer to our wrapped \p _sink 82 : */ 83 : void emit_from_thread_local_buffer(std::string & b, bool force_flush); 84 : 85 : /// Wrapped output sink 86 : std::streambuf & _sink; 87 : /// Whether to flush our sink to terminal/file on terminating new-line characters (\n) 88 : const bool _flush_on_newline; 89 : 90 : /// Serialization for commits to the shared sink 91 : std::unique_ptr<Threads::spin_mutex> _mu; 92 : }; 93 : 94 : } 95 : #endif // LIBMESH_THREAD_BUFFERED_SYNCBUF_H