StreamTee.h revision 344779
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 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(); 68 if (strm) 69 strm->Flush(); 70 } 71 } 72 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); 77 return new_idx; 78 } 79 80 size_t GetNumStreams() const { 81 size_t result = 0; 82 { 83 std::lock_guard<std::recursive_mutex> guard(m_streams_mutex); 84 result = m_streams.size(); 85 } 86 return result; 87 } 88 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]; 94 return stream_sp; 95 } 96 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; 105 } 106 107protected: 108 typedef std::vector<lldb::StreamSP> collection; 109 mutable std::recursive_mutex m_streams_mutex; 110 collection m_streams; 111 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()) 115 return 0; 116 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(); 124 if (strm) { 125 const size_t bytes_written = strm->Write(s, length); 126 if (min_bytes_written > bytes_written) 127 min_bytes_written = bytes_written; 128 } 129 } 130 if (min_bytes_written == SIZE_MAX) 131 return 0; 132 return min_bytes_written; 133 } 134}; 135 136} // namespace lldb_private 137 138#endif // liblldb_StreamTee_h_ 139