StreamTee.h revision 317027
1//===-- StreamTee.h ------------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef liblldb_StreamTee_h_ 11#define liblldb_StreamTee_h_ 12 13#include <limits.h> 14 15#include <mutex> 16 17#include "lldb/Utility/Stream.h" 18 19namespace lldb_private { 20 21class StreamTee : public Stream { 22public: 23 StreamTee() : Stream(), m_streams_mutex(), m_streams() {} 24 25 StreamTee(lldb::StreamSP &stream_sp) 26 : Stream(), m_streams_mutex(), m_streams() { 27 // No need to lock mutex during construction 28 if (stream_sp) 29 m_streams.push_back(stream_sp); 30 } 31 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 35 if (stream_sp) 36 m_streams.push_back(stream_sp); 37 if (stream_2_sp) 38 m_streams.push_back(stream_2_sp); 39 } 40 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; 46 } 47 48 ~StreamTee() override {} 49 50 StreamTee &operator=(const StreamTee &rhs) { 51 if (this != &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; 56 } 57 return *this; 58 } 59 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 65 // the StreamTee to be used with hard coded indexes for clients 66 // that might want N total streams with only a few that are set 67 // to valid values. 68 Stream *strm = pos->get(); 69 if (strm) 70 strm->Flush(); 71 } 72 } 73 74 size_t Write(const void *s, size_t length) override { 75 std::lock_guard<std::recursive_mutex> guard(m_streams_mutex); 76 if (m_streams.empty()) 77 return 0; 78 79 size_t min_bytes_written = SIZE_MAX; 80 collection::iterator pos, end; 81 for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) { 82 // Allow for our collection to contain NULL streams. This allows 83 // the StreamTee to be used with hard coded indexes for clients 84 // that might want N total streams with only a few that are set 85 // to valid values. 86 Stream *strm = pos->get(); 87 if (strm) { 88 const size_t bytes_written = strm->Write(s, length); 89 if (min_bytes_written > bytes_written) 90 min_bytes_written = bytes_written; 91 } 92 } 93 if (min_bytes_written == SIZE_MAX) 94 return 0; 95 return min_bytes_written; 96 } 97 98 size_t AppendStream(const lldb::StreamSP &stream_sp) { 99 size_t new_idx = m_streams.size(); 100 std::lock_guard<std::recursive_mutex> guard(m_streams_mutex); 101 m_streams.push_back(stream_sp); 102 return new_idx; 103 } 104 105 size_t GetNumStreams() const { 106 size_t result = 0; 107 { 108 std::lock_guard<std::recursive_mutex> guard(m_streams_mutex); 109 result = m_streams.size(); 110 } 111 return result; 112 } 113 114 lldb::StreamSP GetStreamAtIndex(uint32_t idx) { 115 lldb::StreamSP stream_sp; 116 std::lock_guard<std::recursive_mutex> guard(m_streams_mutex); 117 if (idx < m_streams.size()) 118 stream_sp = m_streams[idx]; 119 return stream_sp; 120 } 121 122 void SetStreamAtIndex(uint32_t idx, const lldb::StreamSP &stream_sp) { 123 std::lock_guard<std::recursive_mutex> guard(m_streams_mutex); 124 // Resize our stream vector as necessary to fit as many streams 125 // as needed. This also allows this class to be used with hard 126 // coded indexes that can be used contain many streams, not all 127 // of which are valid. 128 if (idx >= m_streams.size()) 129 m_streams.resize(idx + 1); 130 m_streams[idx] = stream_sp; 131 } 132 133protected: 134 typedef std::vector<lldb::StreamSP> collection; 135 mutable std::recursive_mutex m_streams_mutex; 136 collection m_streams; 137}; 138 139} // namespace lldb_private 140 141#endif // liblldb_StreamTee_h_ 142