]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/include/lldb/Utility/StreamTee.h
Copy googletest 1.8.1 from ^/vendor/google/googletest/1.8.1 to .../contrib/googletest
[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 the
65       // StreamTee to be used with hard coded indexes for clients that might
66       // want N total streams with only a few that are set to valid values.
67       Stream *strm = pos->get();
68       if (strm)
69         strm->Flush();
70     }
71   }
72
73   size_t Write(const void *s, size_t length) override {
74     std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
75     if (m_streams.empty())
76       return 0;
77
78     size_t min_bytes_written = SIZE_MAX;
79     collection::iterator pos, end;
80     for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
81       // Allow for our collection to contain NULL streams. This allows the
82       // StreamTee to be used with hard coded indexes for clients that might
83       // want N total streams with only a few that are set to valid values.
84       Stream *strm = pos->get();
85       if (strm) {
86         const size_t bytes_written = strm->Write(s, length);
87         if (min_bytes_written > bytes_written)
88           min_bytes_written = bytes_written;
89       }
90     }
91     if (min_bytes_written == SIZE_MAX)
92       return 0;
93     return min_bytes_written;
94   }
95
96   size_t AppendStream(const lldb::StreamSP &stream_sp) {
97     size_t new_idx = m_streams.size();
98     std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
99     m_streams.push_back(stream_sp);
100     return new_idx;
101   }
102
103   size_t GetNumStreams() const {
104     size_t result = 0;
105     {
106       std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
107       result = m_streams.size();
108     }
109     return result;
110   }
111
112   lldb::StreamSP GetStreamAtIndex(uint32_t idx) {
113     lldb::StreamSP stream_sp;
114     std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
115     if (idx < m_streams.size())
116       stream_sp = m_streams[idx];
117     return stream_sp;
118   }
119
120   void SetStreamAtIndex(uint32_t idx, const lldb::StreamSP &stream_sp) {
121     std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
122     // Resize our stream vector as necessary to fit as many streams as needed.
123     // This also allows this class to be used with hard coded indexes that can
124     // be used contain many streams, not all of which are valid.
125     if (idx >= m_streams.size())
126       m_streams.resize(idx + 1);
127     m_streams[idx] = stream_sp;
128   }
129
130 protected:
131   typedef std::vector<lldb::StreamSP> collection;
132   mutable std::recursive_mutex m_streams_mutex;
133   collection m_streams;
134 };
135
136 } // namespace lldb_private
137
138 #endif // liblldb_StreamTee_h_