1 //===-- StreamTee.h ------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef liblldb_StreamTee_h_
11 #define liblldb_StreamTee_h_
17 #include "lldb/Utility/Stream.h"
19 namespace lldb_private {
21 class StreamTee : public Stream {
23 StreamTee() : Stream(), m_streams_mutex(), m_streams() {}
25 StreamTee(lldb::StreamSP &stream_sp)
26 : Stream(), m_streams_mutex(), m_streams() {
27 // No need to lock mutex during construction
29 m_streams.push_back(stream_sp);
32 StreamTee(lldb::StreamSP &stream_sp, lldb::StreamSP &stream_2_sp)
33 : Stream(), m_streams_mutex(), m_streams() {
34 // No need to lock mutex during construction
36 m_streams.push_back(stream_sp);
38 m_streams.push_back(stream_2_sp);
41 StreamTee(const StreamTee &rhs)
42 : Stream(rhs), m_streams_mutex(), m_streams() {
43 // Don't copy until we lock down "rhs"
44 std::lock_guard<std::recursive_mutex> guard(rhs.m_streams_mutex);
45 m_streams = rhs.m_streams;
48 ~StreamTee() override {}
50 StreamTee &operator=(const StreamTee &rhs) {
52 Stream::operator=(rhs);
53 std::lock_guard<std::recursive_mutex> lhs_locker(m_streams_mutex);
54 std::lock_guard<std::recursive_mutex> rhs_locker(rhs.m_streams_mutex);
55 m_streams = rhs.m_streams;
60 void Flush() override {
61 std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
62 collection::iterator pos, end;
63 for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
64 // Allow for our collection to contain NULL streams. This allows the
65 // StreamTee to be used with hard coded indexes for clients that might
66 // want N total streams with only a few that are set to valid values.
67 Stream *strm = pos->get();
73 size_t AppendStream(const lldb::StreamSP &stream_sp) {
74 size_t new_idx = m_streams.size();
75 std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
76 m_streams.push_back(stream_sp);
80 size_t GetNumStreams() const {
83 std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
84 result = m_streams.size();
89 lldb::StreamSP GetStreamAtIndex(uint32_t idx) {
90 lldb::StreamSP stream_sp;
91 std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
92 if (idx < m_streams.size())
93 stream_sp = m_streams[idx];
97 void SetStreamAtIndex(uint32_t idx, const lldb::StreamSP &stream_sp) {
98 std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
99 // Resize our stream vector as necessary to fit as many streams as needed.
100 // This also allows this class to be used with hard coded indexes that can
101 // be used contain many streams, not all of which are valid.
102 if (idx >= m_streams.size())
103 m_streams.resize(idx + 1);
104 m_streams[idx] = stream_sp;
108 typedef std::vector<lldb::StreamSP> collection;
109 mutable std::recursive_mutex m_streams_mutex;
110 collection m_streams;
112 size_t WriteImpl(const void *s, size_t length) override {
113 std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
114 if (m_streams.empty())
117 size_t min_bytes_written = SIZE_MAX;
118 collection::iterator pos, end;
119 for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
120 // Allow for our collection to contain NULL streams. This allows the
121 // StreamTee to be used with hard coded indexes for clients that might
122 // want N total streams with only a few that are set to valid values.
123 Stream *strm = pos->get();
125 const size_t bytes_written = strm->Write(s, length);
126 if (min_bytes_written > bytes_written)
127 min_bytes_written = bytes_written;
130 if (min_bytes_written == SIZE_MAX)
132 return min_bytes_written;
136 } // namespace lldb_private
138 #endif // liblldb_StreamTee_h_