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_
15 #include "lldb/Core/Stream.h"
16 #include "lldb/Host/Mutex.h"
18 namespace lldb_private {
20 class StreamTee : public Stream
25 m_streams_mutex (Mutex::eMutexTypeRecursive),
30 StreamTee (lldb::StreamSP &stream_sp):
32 m_streams_mutex (Mutex::eMutexTypeRecursive),
35 // No need to lock mutex during construction
37 m_streams.push_back (stream_sp);
41 StreamTee (lldb::StreamSP &stream_sp, lldb::StreamSP &stream_2_sp) :
43 m_streams_mutex (Mutex::eMutexTypeRecursive),
46 // No need to lock mutex during construction
48 m_streams.push_back (stream_sp);
50 m_streams.push_back (stream_2_sp);
53 StreamTee (const StreamTee &rhs) :
55 m_streams_mutex (Mutex::eMutexTypeRecursive),
56 m_streams() // Don't copy until we lock down "rhs"
58 Mutex::Locker locker (rhs.m_streams_mutex);
59 m_streams = rhs.m_streams;
62 ~StreamTee () override
67 operator = (const StreamTee &rhs)
70 Stream::operator=(rhs);
71 Mutex::Locker lhs_locker (m_streams_mutex);
72 Mutex::Locker rhs_locker (rhs.m_streams_mutex);
73 m_streams = rhs.m_streams;
81 Mutex::Locker locker (m_streams_mutex);
82 collection::iterator pos, end;
83 for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos)
85 // Allow for our collection to contain NULL streams. This allows
86 // the StreamTee to be used with hard coded indexes for clients
87 // that might want N total streams with only a few that are set
89 Stream *strm = pos->get();
96 Write (const void *s, size_t length) override
98 Mutex::Locker locker (m_streams_mutex);
99 if (m_streams.empty())
102 size_t min_bytes_written = SIZE_MAX;
103 collection::iterator pos, end;
104 for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos)
106 // Allow for our collection to contain NULL streams. This allows
107 // the StreamTee to be used with hard coded indexes for clients
108 // that might want N total streams with only a few that are set
110 Stream *strm = pos->get();
113 const size_t bytes_written = strm->Write (s, length);
114 if (min_bytes_written > bytes_written)
115 min_bytes_written = bytes_written;
118 if (min_bytes_written == SIZE_MAX)
120 return min_bytes_written;
124 AppendStream (const lldb::StreamSP &stream_sp)
126 size_t new_idx = m_streams.size();
127 Mutex::Locker locker (m_streams_mutex);
128 m_streams.push_back (stream_sp);
133 GetNumStreams () const
137 Mutex::Locker locker (m_streams_mutex);
138 result = m_streams.size();
144 GetStreamAtIndex (uint32_t idx)
146 lldb::StreamSP stream_sp;
147 Mutex::Locker locker (m_streams_mutex);
148 if (idx < m_streams.size())
149 stream_sp = m_streams[idx];
154 SetStreamAtIndex (uint32_t idx, const lldb::StreamSP& stream_sp)
156 Mutex::Locker locker (m_streams_mutex);
157 // Resize our stream vector as necessary to fit as many streams
158 // as needed. This also allows this class to be used with hard
159 // coded indexes that can be used contain many streams, not all
160 // of which are valid.
161 if (idx >= m_streams.size())
162 m_streams.resize(idx + 1);
163 m_streams[idx] = stream_sp;
167 typedef std::vector<lldb::StreamSP> collection;
168 mutable Mutex m_streams_mutex;
169 collection m_streams;
172 } // namespace lldb_private
174 #endif // liblldb_StreamTee_h_