]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/include/lldb/Utility/StreamTee.h
MFV r337220: 8375 Kernel memory leak in nvpair code
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / include / lldb / Utility / StreamTee.h
1 //===-- StreamTee.h ------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef liblldb_StreamTee_h_
11 #define liblldb_StreamTee_h_
12
13 #include <limits.h>
14
15 #include <mutex>
16
17 #include "lldb/Utility/Stream.h"
18
19 namespace lldb_private {
20
21 class StreamTee : public Stream {
22 public:
23   StreamTee() : Stream(), 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 {}
49
50   StreamTee &operator=(const StreamTee &rhs) {
51     if (this != &rhs) {
52       Stream::operator=(rhs);
53       std::lock_guard<std::recursive_mutex> lhs_locker(m_streams_mutex);
54       std::lock_guard<std::recursive_mutex> rhs_locker(rhs.m_streams_mutex);
55       m_streams = rhs.m_streams;
56     }
57     return *this;
58   }
59
60   void Flush() override {
61     std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
62     collection::iterator pos, end;
63     for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
64       // Allow for our collection to contain NULL streams. This allows
65       // the StreamTee to be used with hard coded indexes for clients
66       // that might want N total streams with only a few that are set
67       // to valid values.
68       Stream *strm = pos->get();
69       if (strm)
70         strm->Flush();
71     }
72   }
73
74   size_t Write(const void *s, size_t length) override {
75     std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
76     if (m_streams.empty())
77       return 0;
78
79     size_t min_bytes_written = SIZE_MAX;
80     collection::iterator pos, end;
81     for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
82       // Allow for our collection to contain NULL streams. This allows
83       // the StreamTee to be used with hard coded indexes for clients
84       // that might want N total streams with only a few that are set
85       // to valid values.
86       Stream *strm = pos->get();
87       if (strm) {
88         const size_t bytes_written = strm->Write(s, length);
89         if (min_bytes_written > bytes_written)
90           min_bytes_written = bytes_written;
91       }
92     }
93     if (min_bytes_written == SIZE_MAX)
94       return 0;
95     return min_bytes_written;
96   }
97
98   size_t AppendStream(const lldb::StreamSP &stream_sp) {
99     size_t new_idx = m_streams.size();
100     std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
101     m_streams.push_back(stream_sp);
102     return new_idx;
103   }
104
105   size_t GetNumStreams() const {
106     size_t result = 0;
107     {
108       std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
109       result = m_streams.size();
110     }
111     return result;
112   }
113
114   lldb::StreamSP GetStreamAtIndex(uint32_t idx) {
115     lldb::StreamSP stream_sp;
116     std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
117     if (idx < m_streams.size())
118       stream_sp = m_streams[idx];
119     return stream_sp;
120   }
121
122   void SetStreamAtIndex(uint32_t idx, const lldb::StreamSP &stream_sp) {
123     std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
124     // Resize our stream vector as necessary to fit as many streams
125     // as needed. This also allows this class to be used with hard
126     // coded indexes that can be used contain many streams, not all
127     // of which are valid.
128     if (idx >= m_streams.size())
129       m_streams.resize(idx + 1);
130     m_streams[idx] = stream_sp;
131   }
132
133 protected:
134   typedef std::vector<lldb::StreamSP> collection;
135   mutable std::recursive_mutex m_streams_mutex;
136   collection m_streams;
137 };
138
139 } // namespace lldb_private
140
141 #endif // liblldb_StreamTee_h_