Line data Source code
1 : // The libMesh Finite Element Library. 2 : // Copyright (C) 2002-2026 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 : #include "libmesh/threads_spin_mutex_forward.h" 26 : 27 : namespace libMesh 28 : { 29 : 30 2808 : class ThreadBufferedSyncbuf : public std::streambuf 31 : { 32 : public: 33 : explicit ThreadBufferedSyncbuf(std::streambuf & sink, bool flush_on_newline = true); 34 : 35 : /** 36 : * Defaulted destructor defined in implementation so we don't need to include threads.h 37 : */ 38 : ~ThreadBufferedSyncbuf(); 39 : 40 : protected: 41 : // Single-char path 42 : int_type overflow(int_type ch) override; 43 : 44 : // Bulk write path 45 : std::streamsize xsputn(const char * s, std::streamsize n) override; 46 : 47 : // Flush path (std::flush / std::endl / ostream::flush) 48 : int sync() override; 49 : 50 : private: 51 : /** 52 : * A class that wraps a thread-local string. We make sure when we're destructing and our buffer is 53 : * non-empty to write to our main output sink 54 : */ 55 : class ThreadLocalBuffer 56 : { 57 : public: 58 16800 : explicit ThreadLocalBuffer(ThreadBufferedSyncbuf & owner) : _owner(owner) {} 59 : 60 : /** 61 : * Ensures we write to our sink upon destruction if our buf is non-empty 62 : */ 63 : ~ThreadLocalBuffer(); 64 : 65 : /// per-thread buffer 66 : std::string buf; 67 : 68 : private: 69 : /// owning syncing stream buffer 70 : ThreadBufferedSyncbuf & _owner; 71 : }; 72 : 73 : /** 74 : * One ThreadLocalBuffer instance per thread, constructed on first use with *this. 75 : */ 76 : ThreadLocalBuffer & thread_local_buffer(); 77 : 78 : /** 79 : * Emit from the thread local buffer to our wrapped \p _sink 80 : */ 81 : void emit_from_thread_local_buffer(std::string & b, bool force_flush); 82 : 83 : /// Wrapped output sink 84 : std::streambuf & _sink; 85 : /// Whether to flush our sink to terminal/file on terminating new-line characters (\n) 86 : const bool _flush_on_newline; 87 : 88 : /// Serialization for commits to the shared sink 89 : std::unique_ptr<Threads::spin_mutex> _mu; 90 : }; 91 : 92 : } 93 : #endif // LIBMESH_THREAD_BUFFERED_SYNCBUF_H