| //===-- StreamTee.h ------------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef liblldb_StreamTee_h_ |
| #define liblldb_StreamTee_h_ |
| |
| #include <limits.h> |
| |
| #include "lldb/Core/Stream.h" |
| #include "lldb/Host/Mutex.h" |
| |
| namespace lldb_private { |
| |
| class StreamTee : public Stream |
| { |
| public: |
| StreamTee () : |
| Stream (), |
| m_streams_mutex (Mutex::eMutexTypeRecursive), |
| m_streams () |
| { |
| } |
| |
| StreamTee (lldb::StreamSP &stream_sp): |
| Stream (), |
| m_streams_mutex (Mutex::eMutexTypeRecursive), |
| m_streams () |
| { |
| // No need to lock mutex during construction |
| if (stream_sp) |
| m_streams.push_back (stream_sp); |
| } |
| |
| |
| StreamTee (lldb::StreamSP &stream_sp, lldb::StreamSP &stream_2_sp) : |
| Stream (), |
| m_streams_mutex (Mutex::eMutexTypeRecursive), |
| m_streams () |
| { |
| // No need to lock mutex during construction |
| if (stream_sp) |
| m_streams.push_back (stream_sp); |
| if (stream_2_sp) |
| m_streams.push_back (stream_2_sp); |
| } |
| |
| StreamTee (const StreamTee &rhs) : |
| Stream (rhs), |
| m_streams_mutex (Mutex::eMutexTypeRecursive), |
| m_streams() // Don't copy until we lock down "rhs" |
| { |
| Mutex::Locker locker (rhs.m_streams_mutex); |
| m_streams = rhs.m_streams; |
| } |
| |
| virtual |
| ~StreamTee () |
| { |
| } |
| |
| StreamTee & |
| operator = (const StreamTee &rhs) |
| { |
| if (this != &rhs) { |
| Stream::operator=(rhs); |
| Mutex::Locker lhs_locker (m_streams_mutex); |
| Mutex::Locker rhs_locker (rhs.m_streams_mutex); |
| m_streams = rhs.m_streams; |
| } |
| return *this; |
| } |
| |
| virtual void |
| Flush () |
| { |
| Mutex::Locker locker (m_streams_mutex); |
| collection::iterator pos, end; |
| for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) |
| { |
| // Allow for our collection to contain NULL streams. This allows |
| // the StreamTee to be used with hard coded indexes for clients |
| // that might want N total streams with only a few that are set |
| // to valid values. |
| Stream *strm = pos->get(); |
| if (strm) |
| strm->Flush (); |
| } |
| } |
| |
| virtual size_t |
| Write (const void *s, size_t length) |
| { |
| Mutex::Locker locker (m_streams_mutex); |
| if (m_streams.empty()) |
| return 0; |
| |
| size_t min_bytes_written = SIZE_MAX; |
| collection::iterator pos, end; |
| for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) |
| { |
| // Allow for our collection to contain NULL streams. This allows |
| // the StreamTee to be used with hard coded indexes for clients |
| // that might want N total streams with only a few that are set |
| // to valid values. |
| Stream *strm = pos->get(); |
| if (strm) |
| { |
| const size_t bytes_written = strm->Write (s, length); |
| if (min_bytes_written > bytes_written) |
| min_bytes_written = bytes_written; |
| } |
| } |
| if (min_bytes_written == SIZE_MAX) |
| return 0; |
| return min_bytes_written; |
| } |
| |
| size_t |
| AppendStream (const lldb::StreamSP &stream_sp) |
| { |
| size_t new_idx = m_streams.size(); |
| Mutex::Locker locker (m_streams_mutex); |
| m_streams.push_back (stream_sp); |
| return new_idx; |
| } |
| |
| size_t |
| GetNumStreams () const |
| { |
| size_t result = 0; |
| { |
| Mutex::Locker locker (m_streams_mutex); |
| result = m_streams.size(); |
| } |
| return result; |
| } |
| |
| lldb::StreamSP |
| GetStreamAtIndex (uint32_t idx) |
| { |
| lldb::StreamSP stream_sp; |
| Mutex::Locker locker (m_streams_mutex); |
| if (idx < m_streams.size()) |
| stream_sp = m_streams[idx]; |
| return stream_sp; |
| } |
| |
| void |
| SetStreamAtIndex (uint32_t idx, const lldb::StreamSP& stream_sp) |
| { |
| Mutex::Locker locker (m_streams_mutex); |
| // Resize our stream vector as necessary to fit as many streams |
| // as needed. This also allows this class to be used with hard |
| // coded indexes that can be used contain many streams, not all |
| // of which are valid. |
| if (idx >= m_streams.size()) |
| m_streams.resize(idx + 1); |
| m_streams[idx] = stream_sp; |
| } |
| |
| |
| protected: |
| typedef std::vector<lldb::StreamSP> collection; |
| mutable Mutex m_streams_mutex; |
| collection m_streams; |
| }; |
| |
| } // namespace lldb_private |
| #endif // #ifndef liblldb_StreamTee_h_ |