Home | History | Annotate | Download | only in Core
      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     virtual
     63     ~StreamTee ()
     64     {
     65     }
     66 
     67     StreamTee &
     68     operator = (const StreamTee &rhs)
     69     {
     70         if (this != &rhs) {
     71             Stream::operator=(rhs);
     72             Mutex::Locker lhs_locker (m_streams_mutex);
     73             Mutex::Locker rhs_locker (rhs.m_streams_mutex);
     74             m_streams = rhs.m_streams;
     75         }
     76         return *this;
     77     }
     78 
     79     virtual void
     80     Flush ()
     81     {
     82         Mutex::Locker locker (m_streams_mutex);
     83         collection::iterator pos, end;
     84         for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos)
     85         {
     86             // Allow for our collection to contain NULL streams. This allows
     87             // the StreamTee to be used with hard coded indexes for clients
     88             // that might want N total streams with only a few that are set
     89             // to valid values.
     90             Stream *strm = pos->get();
     91             if (strm)
     92                 strm->Flush ();
     93         }
     94     }
     95 
     96     virtual size_t
     97     Write (const void *s, size_t length)
     98     {
     99         Mutex::Locker locker (m_streams_mutex);
    100         if (m_streams.empty())
    101             return 0;
    102 
    103         size_t min_bytes_written = SIZE_MAX;
    104         collection::iterator pos, end;
    105         for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos)
    106         {
    107             // Allow for our collection to contain NULL streams. This allows
    108             // the StreamTee to be used with hard coded indexes for clients
    109             // that might want N total streams with only a few that are set
    110             // to valid values.
    111             Stream *strm = pos->get();
    112             if (strm)
    113             {
    114                 const size_t bytes_written = strm->Write (s, length);
    115                 if (min_bytes_written > bytes_written)
    116                     min_bytes_written = bytes_written;
    117             }
    118         }
    119         if (min_bytes_written == SIZE_MAX)
    120             return 0;
    121         return min_bytes_written;
    122     }
    123 
    124     size_t
    125     AppendStream (const lldb::StreamSP &stream_sp)
    126     {
    127         size_t new_idx = m_streams.size();
    128         Mutex::Locker locker (m_streams_mutex);
    129         m_streams.push_back (stream_sp);
    130         return new_idx;
    131     }
    132 
    133     size_t
    134     GetNumStreams () const
    135     {
    136         size_t result = 0;
    137         {
    138             Mutex::Locker locker (m_streams_mutex);
    139             result = m_streams.size();
    140         }
    141         return result;
    142     }
    143 
    144     lldb::StreamSP
    145     GetStreamAtIndex (uint32_t idx)
    146     {
    147         lldb::StreamSP stream_sp;
    148         Mutex::Locker locker (m_streams_mutex);
    149         if (idx < m_streams.size())
    150             stream_sp = m_streams[idx];
    151         return stream_sp;
    152     }
    153 
    154     void
    155     SetStreamAtIndex (uint32_t idx, const lldb::StreamSP& stream_sp)
    156     {
    157         Mutex::Locker locker (m_streams_mutex);
    158         // Resize our stream vector as necessary to fit as many streams
    159         // as needed. This also allows this class to be used with hard
    160         // coded indexes that can be used contain many streams, not all
    161         // of which are valid.
    162         if (idx >= m_streams.size())
    163             m_streams.resize(idx + 1);
    164         m_streams[idx] = stream_sp;
    165     }
    166 
    167 
    168 protected:
    169     typedef std::vector<lldb::StreamSP> collection;
    170     mutable Mutex m_streams_mutex;
    171     collection m_streams;
    172 };
    173 
    174 } // namespace lldb_private
    175 #endif  // #ifndef liblldb_StreamTee_h_
    176