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