]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/include/lldb/Core/StreamTee.h
MFV r308954:
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / include / lldb / Core / 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 "lldb/Core/Stream.h"
16 #include "lldb/Host/Mutex.h"
17
18 namespace lldb_private {
19
20 class StreamTee : public Stream
21 {
22 public:
23     StreamTee () :
24         Stream (),
25         m_streams_mutex (Mutex::eMutexTypeRecursive),
26         m_streams ()
27     {
28     }
29
30     StreamTee (lldb::StreamSP &stream_sp):
31         Stream (),
32         m_streams_mutex (Mutex::eMutexTypeRecursive),
33         m_streams ()
34     {
35         // No need to lock mutex during construction
36         if (stream_sp)
37             m_streams.push_back (stream_sp);
38     }
39     
40
41     StreamTee (lldb::StreamSP &stream_sp, lldb::StreamSP &stream_2_sp) :
42         Stream (),
43         m_streams_mutex (Mutex::eMutexTypeRecursive),
44         m_streams ()
45     {
46         // No need to lock mutex during construction
47         if (stream_sp)
48             m_streams.push_back (stream_sp);
49         if (stream_2_sp)
50             m_streams.push_back (stream_2_sp);
51     }
52     
53     StreamTee (const StreamTee &rhs) :
54         Stream (rhs),
55         m_streams_mutex (Mutex::eMutexTypeRecursive),
56         m_streams() // Don't copy until we lock down "rhs"
57     {
58         Mutex::Locker locker (rhs.m_streams_mutex);
59         m_streams = rhs.m_streams;
60     }
61
62     ~StreamTee () override
63     {
64     }
65
66     StreamTee &
67     operator = (const StreamTee &rhs)
68     {
69         if (this != &rhs) {
70             Stream::operator=(rhs);
71             Mutex::Locker lhs_locker (m_streams_mutex);
72             Mutex::Locker rhs_locker (rhs.m_streams_mutex);
73             m_streams = rhs.m_streams;            
74         }
75         return *this;
76     }
77
78     void
79     Flush () override
80     {
81         Mutex::Locker locker (m_streams_mutex);
82         collection::iterator pos, end;
83         for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos)
84         {
85             // Allow for our collection to contain NULL streams. This allows
86             // the StreamTee to be used with hard coded indexes for clients
87             // that might want N total streams with only a few that are set
88             // to valid values.
89             Stream *strm = pos->get();
90             if (strm)
91                 strm->Flush ();
92         }
93     }
94
95     size_t
96     Write (const void *s, size_t length) override
97     {
98         Mutex::Locker locker (m_streams_mutex);
99         if (m_streams.empty())
100             return 0;
101     
102         size_t min_bytes_written = SIZE_MAX;
103         collection::iterator pos, end;
104         for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos)
105         {
106             // Allow for our collection to contain NULL streams. This allows
107             // the StreamTee to be used with hard coded indexes for clients
108             // that might want N total streams with only a few that are set
109             // to valid values.
110             Stream *strm = pos->get();
111             if (strm)
112             {
113                 const size_t bytes_written = strm->Write (s, length);
114                 if (min_bytes_written > bytes_written)
115                     min_bytes_written = bytes_written;
116             }
117         }
118         if (min_bytes_written == SIZE_MAX)
119             return 0;
120         return min_bytes_written;
121     }
122
123     size_t
124     AppendStream (const lldb::StreamSP &stream_sp)
125     {
126         size_t new_idx = m_streams.size();
127         Mutex::Locker locker (m_streams_mutex);
128         m_streams.push_back (stream_sp);
129         return new_idx;
130     }
131
132     size_t
133     GetNumStreams () const
134     {
135         size_t result = 0;
136         {
137             Mutex::Locker locker (m_streams_mutex);
138             result = m_streams.size();
139         }
140         return result;
141     }
142
143     lldb::StreamSP
144     GetStreamAtIndex (uint32_t idx)
145     {
146         lldb::StreamSP stream_sp;
147         Mutex::Locker locker (m_streams_mutex);
148         if (idx < m_streams.size())
149             stream_sp = m_streams[idx];
150         return stream_sp;
151     }
152
153     void
154     SetStreamAtIndex (uint32_t idx, const lldb::StreamSP& stream_sp)
155     {
156         Mutex::Locker locker (m_streams_mutex);
157         // Resize our stream vector as necessary to fit as many streams
158         // as needed. This also allows this class to be used with hard
159         // coded indexes that can be used contain many streams, not all
160         // of which are valid.
161         if (idx >= m_streams.size())
162             m_streams.resize(idx + 1);
163         m_streams[idx] = stream_sp;
164     }
165     
166 protected:
167     typedef std::vector<lldb::StreamSP> collection;
168     mutable Mutex m_streams_mutex;
169     collection m_streams;
170 };
171
172 } // namespace lldb_private
173
174 #endif // liblldb_StreamTee_h_