Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:42:58

0001 //===-- StreamTee.h ------------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLDB_UTILITY_STREAMTEE_H
0010 #define LLDB_UTILITY_STREAMTEE_H
0011 
0012 #include <climits>
0013 
0014 #include <mutex>
0015 
0016 #include "lldb/Utility/Stream.h"
0017 
0018 namespace lldb_private {
0019 
0020 class StreamTee : public Stream {
0021 public:
0022   StreamTee(bool colors = false) : Stream(colors) {}
0023 
0024   StreamTee(lldb::StreamSP &stream_sp) {
0025     // No need to lock mutex during construction
0026     if (stream_sp)
0027       m_streams.push_back(stream_sp);
0028   }
0029 
0030   StreamTee(lldb::StreamSP &stream_sp, lldb::StreamSP &stream_2_sp) {
0031     // No need to lock mutex during construction
0032     if (stream_sp)
0033       m_streams.push_back(stream_sp);
0034     if (stream_2_sp)
0035       m_streams.push_back(stream_2_sp);
0036   }
0037 
0038   StreamTee(const StreamTee &rhs) : Stream(rhs) {
0039     // Don't copy until we lock down "rhs"
0040     std::lock_guard<std::recursive_mutex> guard(rhs.m_streams_mutex);
0041     m_streams = rhs.m_streams;
0042   }
0043 
0044   ~StreamTee() override = default;
0045 
0046   StreamTee &operator=(const StreamTee &rhs) {
0047     if (this != &rhs) {
0048       Stream::operator=(rhs);
0049       std::lock(m_streams_mutex, rhs.m_streams_mutex);
0050       std::lock_guard<std::recursive_mutex> lhs_locker(m_streams_mutex,
0051                                                        std::adopt_lock);
0052       std::lock_guard<std::recursive_mutex> rhs_locker(rhs.m_streams_mutex,
0053                                                        std::adopt_lock);
0054       m_streams = rhs.m_streams;
0055     }
0056     return *this;
0057   }
0058 
0059   void Flush() override {
0060     std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
0061     collection::iterator pos, end;
0062     for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
0063       // Allow for our collection to contain NULL streams. This allows the
0064       // StreamTee to be used with hard coded indexes for clients that might
0065       // want N total streams with only a few that are set to valid values.
0066       Stream *strm = pos->get();
0067       if (strm)
0068         strm->Flush();
0069     }
0070   }
0071 
0072   size_t AppendStream(const lldb::StreamSP &stream_sp) {
0073     size_t new_idx = m_streams.size();
0074     std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
0075     m_streams.push_back(stream_sp);
0076     return new_idx;
0077   }
0078 
0079   size_t GetNumStreams() const {
0080     size_t result = 0;
0081     {
0082       std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
0083       result = m_streams.size();
0084     }
0085     return result;
0086   }
0087 
0088   lldb::StreamSP GetStreamAtIndex(uint32_t idx) {
0089     lldb::StreamSP stream_sp;
0090     std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
0091     if (idx < m_streams.size())
0092       stream_sp = m_streams[idx];
0093     return stream_sp;
0094   }
0095 
0096   void SetStreamAtIndex(uint32_t idx, const lldb::StreamSP &stream_sp) {
0097     std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
0098     // Resize our stream vector as necessary to fit as many streams as needed.
0099     // This also allows this class to be used with hard coded indexes that can
0100     // be used contain many streams, not all of which are valid.
0101     if (idx >= m_streams.size())
0102       m_streams.resize(idx + 1);
0103     m_streams[idx] = stream_sp;
0104   }
0105 
0106 protected:
0107   typedef std::vector<lldb::StreamSP> collection;
0108   mutable std::recursive_mutex m_streams_mutex;
0109   collection m_streams;
0110 
0111   size_t WriteImpl(const void *s, size_t length) override {
0112     std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
0113     if (m_streams.empty())
0114       return 0;
0115 
0116     size_t min_bytes_written = SIZE_MAX;
0117     collection::iterator pos, end;
0118     for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
0119       // Allow for our collection to contain NULL streams. This allows the
0120       // StreamTee to be used with hard coded indexes for clients that might
0121       // want N total streams with only a few that are set to valid values.
0122       Stream *strm = pos->get();
0123       if (strm) {
0124         const size_t bytes_written = strm->Write(s, length);
0125         if (min_bytes_written > bytes_written)
0126           min_bytes_written = bytes_written;
0127       }
0128     }
0129     if (min_bytes_written == SIZE_MAX)
0130       return 0;
0131     return min_bytes_written;
0132   }
0133 };
0134 
0135 } // namespace lldb_private
0136 
0137 #endif // LLDB_UTILITY_STREAMTEE_H