StreamTee.h revision 317032
148187Skato//===-- StreamTee.h ------------------------------------------*- C++ -*-===//
248516Skato//
348516Skato//                     The LLVM Compiler Infrastructure
448516Skato//
548516Skato// This file is distributed under the University of Illinois Open Source
648516Skato// License. See LICENSE.TXT for details.
748516Skato//
848516Skato//===----------------------------------------------------------------------===//
948516Skato
1048516Skato#ifndef liblldb_StreamTee_h_
1148516Skato#define liblldb_StreamTee_h_
1248516Skato
1348516Skato#include <limits.h>
1448516Skato
1548516Skato#include <mutex>
1648516Skato
1748516Skato#include "lldb/Utility/Stream.h"
1848516Skato
1948516Skatonamespace lldb_private {
2048516Skato
2148516Skatoclass StreamTee : public Stream {
2248516Skatopublic:
2348516Skato  StreamTee() : Stream(), m_streams_mutex(), m_streams() {}
2448516Skato
2548516Skato  StreamTee(lldb::StreamSP &stream_sp)
2650477Speter      : Stream(), m_streams_mutex(), m_streams() {
2748187Skato    // No need to lock mutex during construction
2848187Skato    if (stream_sp)
2948187Skato      m_streams.push_back(stream_sp);
3048187Skato  }
3148187Skato
3248187Skato  StreamTee(lldb::StreamSP &stream_sp, lldb::StreamSP &stream_2_sp)
3383875Snyan      : Stream(), m_streams_mutex(), m_streams() {
3448187Skato    // No need to lock mutex during construction
35130070Sphk    if (stream_sp)
3683875Snyan      m_streams.push_back(stream_sp);
3766870Skato    if (stream_2_sp)
3848187Skato      m_streams.push_back(stream_2_sp);
3948187Skato  }
4048187Skato
4148187Skato  StreamTee(const StreamTee &rhs)
4248187Skato      : Stream(rhs), m_streams_mutex(), m_streams() {
4348187Skato    // Don't copy until we lock down "rhs"
4448187Skato    std::lock_guard<std::recursive_mutex> guard(rhs.m_streams_mutex);
4548187Skato    m_streams = rhs.m_streams;
4648187Skato  }
4748187Skato
4848187Skato  ~StreamTee() override {}
4948187Skato
5048187Skato  StreamTee &operator=(const StreamTee &rhs) {
5148187Skato    if (this != &rhs) {
5248187Skato      Stream::operator=(rhs);
5348187Skato      std::lock_guard<std::recursive_mutex> lhs_locker(m_streams_mutex);
5448187Skato      std::lock_guard<std::recursive_mutex> rhs_locker(rhs.m_streams_mutex);
5548187Skato      m_streams = rhs.m_streams;
5648187Skato    }
5748187Skato    return *this;
5848187Skato  }
5948187Skato
6048187Skato  void Flush() override {
6148187Skato    std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
6248187Skato    collection::iterator pos, end;
6348187Skato    for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
6448187Skato      // Allow for our collection to contain NULL streams. This allows
6548187Skato      // the StreamTee to be used with hard coded indexes for clients
6648187Skato      // that might want N total streams with only a few that are set
6748187Skato      // to valid values.
6848187Skato      Stream *strm = pos->get();
6948187Skato      if (strm)
7048187Skato        strm->Flush();
7148187Skato    }
7248187Skato  }
7356337Skato
7448187Skato  size_t Write(const void *s, size_t length) override {
7548187Skato    std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
7648187Skato    if (m_streams.empty())
7748187Skato      return 0;
7848187Skato
7948187Skato    size_t min_bytes_written = SIZE_MAX;
8048187Skato    collection::iterator pos, end;
8148187Skato    for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
8248187Skato      // Allow for our collection to contain NULL streams. This allows
8348187Skato      // the StreamTee to be used with hard coded indexes for clients
8448187Skato      // that might want N total streams with only a few that are set
8548187Skato      // to valid values.
8656337Skato      Stream *strm = pos->get();
8748187Skato      if (strm) {
8848187Skato        const size_t bytes_written = strm->Write(s, length);
8956337Skato        if (min_bytes_written > bytes_written)
9056337Skato          min_bytes_written = bytes_written;
9148187Skato      }
9248187Skato    }
9348187Skato    if (min_bytes_written == SIZE_MAX)
9448187Skato      return 0;
9548187Skato    return min_bytes_written;
9648187Skato  }
9748187Skato
9848187Skato  size_t AppendStream(const lldb::StreamSP &stream_sp) {
9948187Skato    size_t new_idx = m_streams.size();
10048187Skato    std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
10148187Skato    m_streams.push_back(stream_sp);
10248187Skato    return new_idx;
10348187Skato  }
10448187Skato
10548187Skato  size_t GetNumStreams() const {
10648187Skato    size_t result = 0;
10748187Skato    {
10848187Skato      std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
10948187Skato      result = m_streams.size();
11048187Skato    }
11148187Skato    return result;
11248187Skato  }
11348187Skato
11448187Skato  lldb::StreamSP GetStreamAtIndex(uint32_t idx) {
11548187Skato    lldb::StreamSP stream_sp;
11648187Skato    std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
11748187Skato    if (idx < m_streams.size())
11848187Skato      stream_sp = m_streams[idx];
11948187Skato    return stream_sp;
12048187Skato  }
12190464Snyan
12248187Skato  void SetStreamAtIndex(uint32_t idx, const lldb::StreamSP &stream_sp) {
12390464Snyan    std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
12490464Snyan    // Resize our stream vector as necessary to fit as many streams
12590464Snyan    // as needed. This also allows this class to be used with hard
12690464Snyan    // coded indexes that can be used contain many streams, not all
12790464Snyan    // of which are valid.
12890464Snyan    if (idx >= m_streams.size())
12990464Snyan      m_streams.resize(idx + 1);
13087886Snyan    m_streams[idx] = stream_sp;
13148187Skato  }
13248187Skato
13348187Skatoprotected:
13448187Skato  typedef std::vector<lldb::StreamSP> collection;
13548187Skato  mutable std::recursive_mutex m_streams_mutex;
13648187Skato  collection m_streams;
13748187Skato};
13848187Skato
13948187Skato} // namespace lldb_private
14048187Skato
14148187Skato#endif // liblldb_StreamTee_h_
14248187Skato