File indexing completed on 2026-05-10 08:42:58
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLDB_UTILITY_STREAMTEE_H
0010 #define LLDB_UTILITY_STREAMTEE_H
0011
0012 #include <climits>
0013
0014 #include <mutex>
0015
0016 #include "lldb/Utility/Stream.h"
0017
0018 namespace lldb_private {
0019
0020 class StreamTee : public Stream {
0021 public:
0022 StreamTee(bool colors = false) : Stream(colors) {}
0023
0024 StreamTee(lldb::StreamSP &stream_sp) {
0025
0026 if (stream_sp)
0027 m_streams.push_back(stream_sp);
0028 }
0029
0030 StreamTee(lldb::StreamSP &stream_sp, lldb::StreamSP &stream_2_sp) {
0031
0032 if (stream_sp)
0033 m_streams.push_back(stream_sp);
0034 if (stream_2_sp)
0035 m_streams.push_back(stream_2_sp);
0036 }
0037
0038 StreamTee(const StreamTee &rhs) : Stream(rhs) {
0039
0040 std::lock_guard<std::recursive_mutex> guard(rhs.m_streams_mutex);
0041 m_streams = rhs.m_streams;
0042 }
0043
0044 ~StreamTee() override = default;
0045
0046 StreamTee &operator=(const StreamTee &rhs) {
0047 if (this != &rhs) {
0048 Stream::operator=(rhs);
0049 std::lock(m_streams_mutex, rhs.m_streams_mutex);
0050 std::lock_guard<std::recursive_mutex> lhs_locker(m_streams_mutex,
0051 std::adopt_lock);
0052 std::lock_guard<std::recursive_mutex> rhs_locker(rhs.m_streams_mutex,
0053 std::adopt_lock);
0054 m_streams = rhs.m_streams;
0055 }
0056 return *this;
0057 }
0058
0059 void Flush() override {
0060 std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
0061 collection::iterator pos, end;
0062 for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
0063
0064
0065
0066 Stream *strm = pos->get();
0067 if (strm)
0068 strm->Flush();
0069 }
0070 }
0071
0072 size_t AppendStream(const lldb::StreamSP &stream_sp) {
0073 size_t new_idx = m_streams.size();
0074 std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
0075 m_streams.push_back(stream_sp);
0076 return new_idx;
0077 }
0078
0079 size_t GetNumStreams() const {
0080 size_t result = 0;
0081 {
0082 std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
0083 result = m_streams.size();
0084 }
0085 return result;
0086 }
0087
0088 lldb::StreamSP GetStreamAtIndex(uint32_t idx) {
0089 lldb::StreamSP stream_sp;
0090 std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
0091 if (idx < m_streams.size())
0092 stream_sp = m_streams[idx];
0093 return stream_sp;
0094 }
0095
0096 void SetStreamAtIndex(uint32_t idx, const lldb::StreamSP &stream_sp) {
0097 std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
0098
0099
0100
0101 if (idx >= m_streams.size())
0102 m_streams.resize(idx + 1);
0103 m_streams[idx] = stream_sp;
0104 }
0105
0106 protected:
0107 typedef std::vector<lldb::StreamSP> collection;
0108 mutable std::recursive_mutex m_streams_mutex;
0109 collection m_streams;
0110
0111 size_t WriteImpl(const void *s, size_t length) override {
0112 std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
0113 if (m_streams.empty())
0114 return 0;
0115
0116 size_t min_bytes_written = SIZE_MAX;
0117 collection::iterator pos, end;
0118 for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
0119
0120
0121
0122 Stream *strm = pos->get();
0123 if (strm) {
0124 const size_t bytes_written = strm->Write(s, length);
0125 if (min_bytes_written > bytes_written)
0126 min_bytes_written = bytes_written;
0127 }
0128 }
0129 if (min_bytes_written == SIZE_MAX)
0130 return 0;
0131 return min_bytes_written;
0132 }
0133 };
0134
0135 }
0136
0137 #endif