StreamTee.h revision 341825
1143439Sobrien//===-- StreamTee.h ------------------------------------------*- C++ -*-===// 2143439Sobrien// 3143439Sobrien// The LLVM Compiler Infrastructure 4143439Sobrien// 5143439Sobrien// This file is distributed under the University of Illinois Open Source 6143439Sobrien// License. See LICENSE.TXT for details. 7143439Sobrien// 8143439Sobrien//===----------------------------------------------------------------------===// 9143439Sobrien 10143439Sobrien#ifndef liblldb_StreamTee_h_ 11143439Sobrien#define liblldb_StreamTee_h_ 12143439Sobrien 13143439Sobrien#include <limits.h> 14143439Sobrien 15143439Sobrien#include <mutex> 16143439Sobrien 17143439Sobrien#include "lldb/Utility/Stream.h" 18143439Sobrien 19143439Sobriennamespace lldb_private { 20143439Sobrien 21143439Sobrienclass StreamTee : public Stream { 22143439Sobrienpublic: 23143439Sobrien StreamTee() : Stream(), m_streams_mutex(), m_streams() {} 24143439Sobrien 25143439Sobrien StreamTee(lldb::StreamSP &stream_sp) 26143439Sobrien : Stream(), m_streams_mutex(), m_streams() { 27143439Sobrien // No need to lock mutex during construction 28143439Sobrien if (stream_sp) 29143439Sobrien m_streams.push_back(stream_sp); 30143439Sobrien } 31143439Sobrien 32143439Sobrien StreamTee(lldb::StreamSP &stream_sp, lldb::StreamSP &stream_2_sp) 33143439Sobrien : Stream(), m_streams_mutex(), m_streams() { 34143439Sobrien // No need to lock mutex during construction 35143439Sobrien if (stream_sp) 36143439Sobrien m_streams.push_back(stream_sp); 37143439Sobrien if (stream_2_sp) 38143439Sobrien m_streams.push_back(stream_2_sp); 39143439Sobrien } 40143439Sobrien 41143439Sobrien StreamTee(const StreamTee &rhs) 42143439Sobrien : Stream(rhs), m_streams_mutex(), m_streams() { 43143439Sobrien // Don't copy until we lock down "rhs" 44143439Sobrien std::lock_guard<std::recursive_mutex> guard(rhs.m_streams_mutex); 45143439Sobrien m_streams = rhs.m_streams; 46143439Sobrien } 47143439Sobrien 48143439Sobrien ~StreamTee() override {} 49143439Sobrien 50143439Sobrien StreamTee &operator=(const StreamTee &rhs) { 51143439Sobrien if (this != &rhs) { 52143439Sobrien Stream::operator=(rhs); 53143439Sobrien std::lock_guard<std::recursive_mutex> lhs_locker(m_streams_mutex); 54143439Sobrien std::lock_guard<std::recursive_mutex> rhs_locker(rhs.m_streams_mutex); 55143439Sobrien m_streams = rhs.m_streams; 56143439Sobrien } 57143439Sobrien return *this; 58143439Sobrien } 59143439Sobrien 60143439Sobrien void Flush() override { 61143439Sobrien std::lock_guard<std::recursive_mutex> guard(m_streams_mutex); 62143439Sobrien collection::iterator pos, end; 63143439Sobrien for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) { 64143439Sobrien // Allow for our collection to contain NULL streams. This allows the 65143439Sobrien // StreamTee to be used with hard coded indexes for clients that might 66143439Sobrien // want N total streams with only a few that are set to valid values. 67143439Sobrien Stream *strm = pos->get(); 68143439Sobrien if (strm) 69143439Sobrien strm->Flush(); 70143439Sobrien } 71143439Sobrien } 72143439Sobrien 73143439Sobrien size_t Write(const void *s, size_t length) override { 74143439Sobrien std::lock_guard<std::recursive_mutex> guard(m_streams_mutex); 75143439Sobrien if (m_streams.empty()) 76143439Sobrien return 0; 77143439Sobrien 78143439Sobrien size_t min_bytes_written = SIZE_MAX; 79143439Sobrien collection::iterator pos, end; 80143439Sobrien for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) { 81143439Sobrien // Allow for our collection to contain NULL streams. This allows the 82143439Sobrien // StreamTee to be used with hard coded indexes for clients that might 83143439Sobrien // want N total streams with only a few that are set to valid values. 84143439Sobrien Stream *strm = pos->get(); 85143439Sobrien if (strm) { 86143439Sobrien const size_t bytes_written = strm->Write(s, length); 87143439Sobrien if (min_bytes_written > bytes_written) 88143439Sobrien min_bytes_written = bytes_written; 89143439Sobrien } 90143439Sobrien } 91143439Sobrien if (min_bytes_written == SIZE_MAX) 92143439Sobrien return 0; 93143439Sobrien return min_bytes_written; 94143439Sobrien } 95143439Sobrien 96143439Sobrien size_t AppendStream(const lldb::StreamSP &stream_sp) { 97143439Sobrien size_t new_idx = m_streams.size(); 98143439Sobrien std::lock_guard<std::recursive_mutex> guard(m_streams_mutex); 99143439Sobrien m_streams.push_back(stream_sp); 100143439Sobrien return new_idx; 101143439Sobrien } 102143439Sobrien 103143439Sobrien size_t GetNumStreams() const { 104143439Sobrien size_t result = 0; 105143439Sobrien { 106143439Sobrien std::lock_guard<std::recursive_mutex> guard(m_streams_mutex); 107143439Sobrien result = m_streams.size(); 108143439Sobrien } 109143439Sobrien return result; 110143439Sobrien } 111143439Sobrien 112143439Sobrien lldb::StreamSP GetStreamAtIndex(uint32_t idx) { 113143439Sobrien lldb::StreamSP stream_sp; 114143439Sobrien std::lock_guard<std::recursive_mutex> guard(m_streams_mutex); 115143439Sobrien if (idx < m_streams.size()) 116143439Sobrien stream_sp = m_streams[idx]; 117143439Sobrien return stream_sp; 118143439Sobrien } 119143439Sobrien 120143439Sobrien void SetStreamAtIndex(uint32_t idx, const lldb::StreamSP &stream_sp) { 121143439Sobrien std::lock_guard<std::recursive_mutex> guard(m_streams_mutex); 122143439Sobrien // Resize our stream vector as necessary to fit as many streams as needed. 123143439Sobrien // This also allows this class to be used with hard coded indexes that can 124143439Sobrien // be used contain many streams, not all of which are valid. 125143439Sobrien if (idx >= m_streams.size()) 126143439Sobrien m_streams.resize(idx + 1); 127143439Sobrien m_streams[idx] = stream_sp; 128143439Sobrien } 129143439Sobrien 130143439Sobrienprotected: 131143439Sobrien typedef std::vector<lldb::StreamSP> collection; 132143439Sobrien mutable std::recursive_mutex m_streams_mutex; 133143439Sobrien collection m_streams; 134143439Sobrien}; 135143439Sobrien 136143439Sobrien} // namespace lldb_private 137143439Sobrien 138143439Sobrien#endif // liblldb_StreamTee_h_ 139143439Sobrien