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)
23  : Stream(colors), 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 = default;
49 
50  StreamTee &operator=(const StreamTee &rhs) {
51  if (this != &rhs) {
52  Stream::operator=(rhs);
53  std::lock(m_streams_mutex, rhs.m_streams_mutex);
54  std::lock_guard<std::recursive_mutex> lhs_locker(m_streams_mutex,
55  std::adopt_lock);
56  std::lock_guard<std::recursive_mutex> rhs_locker(rhs.m_streams_mutex,
57  std::adopt_lock);
58  m_streams = rhs.m_streams;
59  }
60  return *this;
61  }
62 
63  void Flush() override {
64  std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
65  collection::iterator pos, end;
66  for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
67  // Allow for our collection to contain NULL streams. This allows the
68  // StreamTee to be used with hard coded indexes for clients that might
69  // want N total streams with only a few that are set to valid values.
70  Stream *strm = pos->get();
71  if (strm)
72  strm->Flush();
73  }
74  }
75 
76  size_t AppendStream(const lldb::StreamSP &stream_sp) {
77  size_t new_idx = m_streams.size();
78  std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
79  m_streams.push_back(stream_sp);
80  return new_idx;
81  }
82 
83  size_t GetNumStreams() const {
84  size_t result = 0;
85  {
86  std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
87  result = m_streams.size();
88  }
89  return result;
90  }
91 
92  lldb::StreamSP GetStreamAtIndex(uint32_t idx) {
93  lldb::StreamSP stream_sp;
94  std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
95  if (idx < m_streams.size())
96  stream_sp = m_streams[idx];
97  return stream_sp;
98  }
99 
100  void SetStreamAtIndex(uint32_t idx, const lldb::StreamSP &stream_sp) {
101  std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
102  // Resize our stream vector as necessary to fit as many streams as needed.
103  // This also allows this class to be used with hard coded indexes that can
104  // be used contain many streams, not all of which are valid.
105  if (idx >= m_streams.size())
106  m_streams.resize(idx + 1);
107  m_streams[idx] = stream_sp;
108  }
109 
110 protected:
111  typedef std::vector<lldb::StreamSP> collection;
112  mutable std::recursive_mutex m_streams_mutex;
114 
115  size_t WriteImpl(const void *s, size_t length) override {
116  std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
117  if (m_streams.empty())
118  return 0;
119 
120  size_t min_bytes_written = SIZE_MAX;
121  collection::iterator pos, end;
122  for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
123  // Allow for our collection to contain NULL streams. This allows the
124  // StreamTee to be used with hard coded indexes for clients that might
125  // want N total streams with only a few that are set to valid values.
126  Stream *strm = pos->get();
127  if (strm) {
128  const size_t bytes_written = strm->Write(s, length);
129  if (min_bytes_written > bytes_written)
130  min_bytes_written = bytes_written;
131  }
132  }
133  if (min_bytes_written == SIZE_MAX)
134  return 0;
135  return min_bytes_written;
136  }
137 };
138 
139 } // namespace lldb_private
140 
141 #endif // LLDB_UTILITY_STREAMTEE_H
lldb_private::StreamTee::m_streams_mutex
std::recursive_mutex m_streams_mutex
Definition: StreamTee.h:112
lldb_private::StreamTee::StreamTee
StreamTee(const StreamTee &rhs)
Definition: StreamTee.h:41
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:113
lldb_private::StreamTee
Definition: StreamTee.h:20
lldb_private::StreamTee::operator=
StreamTee & operator=(const StreamTee &rhs)
Definition: StreamTee.h:50
lldb_private::StreamTee::GetStreamAtIndex
lldb::StreamSP GetStreamAtIndex(uint32_t idx)
Definition: StreamTee.h:92
lldb_private::StreamTee::WriteImpl
size_t WriteImpl(const void *s, size_t length) override
Output character bytes to the stream.
Definition: StreamTee.h:115
lldb_private::StreamTee::SetStreamAtIndex
void SetStreamAtIndex(uint32_t idx, const lldb::StreamSP &stream_sp)
Definition: StreamTee.h:100
lldb_private::StreamTee::Flush
void Flush() override
Flush the stream.
Definition: StreamTee.h:63
uint32_t
lldb_private::StreamTee::GetNumStreams
size_t GetNumStreams() const
Definition: StreamTee.h:83
lldb_private::StreamTee::collection
std::vector< lldb::StreamSP > collection
Definition: StreamTee.h:111
lldb_private::StreamTee::StreamTee
StreamTee(lldb::StreamSP &stream_sp)
Definition: StreamTee.h:25
lldb_private::StreamTee::StreamTee
StreamTee(lldb::StreamSP &stream_sp, lldb::StreamSP &stream_2_sp)
Definition: StreamTee.h:32
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:76