LLDB  mainline
StreamTee.h
Go to the documentation of this file.
1 //===-- StreamTee.h ------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_UTILITY_STREAMTEE_H
10 #define LLDB_UTILITY_STREAMTEE_H
11 
12 #include <climits>
13 
14 #include <mutex>
15 
16 #include "lldb/Utility/Stream.h"
17 
18 namespace lldb_private {
19 
20 class StreamTee : public Stream {
21 public:
22  StreamTee(bool colors = false) : Stream(colors) {}
23 
24  StreamTee(lldb::StreamSP &stream_sp) {
25  // No need to lock mutex during construction
26  if (stream_sp)
27  m_streams.push_back(stream_sp);
28  }
29 
30  StreamTee(lldb::StreamSP &stream_sp, lldb::StreamSP &stream_2_sp) {
31  // No need to lock mutex during construction
32  if (stream_sp)
33  m_streams.push_back(stream_sp);
34  if (stream_2_sp)
35  m_streams.push_back(stream_2_sp);
36  }
37 
38  StreamTee(const StreamTee &rhs) : Stream(rhs) {
39  // Don't copy until we lock down "rhs"
40  std::lock_guard<std::recursive_mutex> guard(rhs.m_streams_mutex);
41  m_streams = rhs.m_streams;
42  }
43 
44  ~StreamTee() override = default;
45 
46  StreamTee &operator=(const StreamTee &rhs) {
47  if (this != &rhs) {
48  Stream::operator=(rhs);
49  std::lock(m_streams_mutex, rhs.m_streams_mutex);
50  std::lock_guard<std::recursive_mutex> lhs_locker(m_streams_mutex,
51  std::adopt_lock);
52  std::lock_guard<std::recursive_mutex> rhs_locker(rhs.m_streams_mutex,
53  std::adopt_lock);
54  m_streams = rhs.m_streams;
55  }
56  return *this;
57  }
58 
59  void Flush() override {
60  std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
61  collection::iterator pos, end;
62  for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
63  // Allow for our collection to contain NULL streams. This allows the
64  // StreamTee to be used with hard coded indexes for clients that might
65  // want N total streams with only a few that are set to valid values.
66  Stream *strm = pos->get();
67  if (strm)
68  strm->Flush();
69  }
70  }
71 
72  size_t AppendStream(const lldb::StreamSP &stream_sp) {
73  size_t new_idx = m_streams.size();
74  std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
75  m_streams.push_back(stream_sp);
76  return new_idx;
77  }
78 
79  size_t GetNumStreams() const {
80  size_t result = 0;
81  {
82  std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
83  result = m_streams.size();
84  }
85  return result;
86  }
87 
88  lldb::StreamSP GetStreamAtIndex(uint32_t idx) {
89  lldb::StreamSP stream_sp;
90  std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
91  if (idx < m_streams.size())
92  stream_sp = m_streams[idx];
93  return stream_sp;
94  }
95 
96  void SetStreamAtIndex(uint32_t idx, const lldb::StreamSP &stream_sp) {
97  std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
98  // Resize our stream vector as necessary to fit as many streams as needed.
99  // This also allows this class to be used with hard coded indexes that can
100  // be used contain many streams, not all of which are valid.
101  if (idx >= m_streams.size())
102  m_streams.resize(idx + 1);
103  m_streams[idx] = stream_sp;
104  }
105 
106 protected:
107  typedef std::vector<lldb::StreamSP> collection;
108  mutable std::recursive_mutex m_streams_mutex;
110 
111  size_t WriteImpl(const void *s, size_t length) override {
112  std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
113  if (m_streams.empty())
114  return 0;
115 
116  size_t min_bytes_written = SIZE_MAX;
117  collection::iterator pos, end;
118  for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
119  // Allow for our collection to contain NULL streams. This allows the
120  // StreamTee to be used with hard coded indexes for clients that might
121  // want N total streams with only a few that are set to valid values.
122  Stream *strm = pos->get();
123  if (strm) {
124  const size_t bytes_written = strm->Write(s, length);
125  if (min_bytes_written > bytes_written)
126  min_bytes_written = bytes_written;
127  }
128  }
129  if (min_bytes_written == SIZE_MAX)
130  return 0;
131  return min_bytes_written;
132  }
133 };
134 
135 } // namespace lldb_private
136 
137 #endif // LLDB_UTILITY_STREAMTEE_H
lldb_private::StreamTee::m_streams_mutex
std::recursive_mutex m_streams_mutex
Definition: StreamTee.h:108
lldb_private::StreamTee::StreamTee
StreamTee(const StreamTee &rhs)
Definition: StreamTee.h:38
lldb_private::Stream::Flush
virtual void Flush()=0
Flush the stream.
lldb_private::Stream::operator=
Stream & operator=(const Stream &rhs)
Definition: Stream.h:70
lldb_private::Stream
Definition: Stream.h:28
lldb_private::StreamTee::m_streams
collection m_streams
Definition: StreamTee.h:109
lldb_private::StreamTee
Definition: StreamTee.h:20
lldb_private::StreamTee::operator=
StreamTee & operator=(const StreamTee &rhs)
Definition: StreamTee.h:46
lldb_private::StreamTee::GetStreamAtIndex
lldb::StreamSP GetStreamAtIndex(uint32_t idx)
Definition: StreamTee.h:88
lldb_private::StreamTee::WriteImpl
size_t WriteImpl(const void *s, size_t length) override
Output character bytes to the stream.
Definition: StreamTee.h:111
lldb_private::StreamTee::SetStreamAtIndex
void SetStreamAtIndex(uint32_t idx, const lldb::StreamSP &stream_sp)
Definition: StreamTee.h:96
lldb_private::StreamTee::Flush
void Flush() override
Flush the stream.
Definition: StreamTee.h:59
uint32_t
lldb_private::StreamTee::GetNumStreams
size_t GetNumStreams() const
Definition: StreamTee.h:79
lldb_private::StreamTee::collection
std::vector< lldb::StreamSP > collection
Definition: StreamTee.h:107
lldb_private::StreamTee::StreamTee
StreamTee(lldb::StreamSP &stream_sp)
Definition: StreamTee.h:24
lldb_private::StreamTee::StreamTee
StreamTee(lldb::StreamSP &stream_sp, lldb::StreamSP &stream_2_sp)
Definition: StreamTee.h:30
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::StreamTee::StreamTee
StreamTee(bool colors=false)
Definition: StreamTee.h:22
lldb_private::Stream::Write
size_t Write(const void *src, size_t src_len)
Output character bytes to the stream.
Definition: Stream.h:101
Stream.h
lldb_private::StreamTee::~StreamTee
~StreamTee() override=default
lldb_private::StreamTee::AppendStream
size_t AppendStream(const lldb::StreamSP &stream_sp)
Definition: StreamTee.h:72