Coverage Report

Created: 2023-11-11 10:31

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Utility/StreamTee.h
Line
Count
Source (jump to first uncovered line)
1
//===-- StreamTee.h ------------------------------------------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#ifndef LLDB_UTILITY_STREAMTEE_H
10
#define LLDB_UTILITY_STREAMTEE_H
11
12
#include <climits>
13
14
#include <mutex>
15
16
#include "lldb/Utility/Stream.h"
17
18
namespace lldb_private {
19
20
class StreamTee : public Stream {
21
public:
22
190k
  StreamTee(bool colors = false) : Stream(colors) {}
23
24
  StreamTee(lldb::StreamSP &stream_sp) {
25
    // No need to lock mutex during construction
26
    if (stream_sp)
27
      m_streams.push_back(stream_sp);
28
  }
29
30
  StreamTee(lldb::StreamSP &stream_sp, lldb::StreamSP &stream_2_sp) {
31
    // No need to lock mutex during construction
32
    if (stream_sp)
33
      m_streams.push_back(stream_sp);
34
    if (stream_2_sp)
35
      m_streams.push_back(stream_2_sp);
36
  }
37
38
166
  StreamTee(const StreamTee &rhs) : Stream(rhs) {
39
    // Don't copy until we lock down "rhs"
40
166
    std::lock_guard<std::recursive_mutex> guard(rhs.m_streams_mutex);
41
166
    m_streams = rhs.m_streams;
42
166
  }
43
44
190k
  ~StreamTee() override = default;
45
46
0
  StreamTee &operator=(const StreamTee &rhs) {
47
0
    if (this != &rhs) {
48
0
      Stream::operator=(rhs);
49
0
      std::lock(m_streams_mutex, rhs.m_streams_mutex);
50
0
      std::lock_guard<std::recursive_mutex> lhs_locker(m_streams_mutex,
51
0
                                                       std::adopt_lock);
52
0
      std::lock_guard<std::recursive_mutex> rhs_locker(rhs.m_streams_mutex,
53
0
                                                       std::adopt_lock);
54
0
      m_streams = rhs.m_streams;
55
0
    }
56
0
    return *this;
57
0
  }
58
59
87
  void Flush() override {
60
87
    std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
61
87
    collection::iterator pos, end;
62
244
    for (pos = m_streams.begin(), end = m_streams.end(); pos != end; 
++pos157
) {
63
      // Allow for our collection to contain NULL streams. This allows the
64
      // StreamTee to be used with hard coded indexes for clients that might
65
      // want N total streams with only a few that are set to valid values.
66
157
      Stream *strm = pos->get();
67
157
      if (strm)
68
157
        strm->Flush();
69
157
    }
70
87
  }
71
72
  size_t AppendStream(const lldb::StreamSP &stream_sp) {
73
    size_t new_idx = m_streams.size();
74
    std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
75
    m_streams.push_back(stream_sp);
76
    return new_idx;
77
  }
78
79
  size_t GetNumStreams() const {
80
    size_t result = 0;
81
    {
82
      std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
83
      result = m_streams.size();
84
    }
85
    return result;
86
  }
87
88
2.86M
  lldb::StreamSP GetStreamAtIndex(uint32_t idx) {
89
2.86M
    lldb::StreamSP stream_sp;
90
2.86M
    std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
91
2.86M
    if (idx < m_streams.size())
92
2.61M
      stream_sp = m_streams[idx];
93
2.86M
    return stream_sp;
94
2.86M
  }
95
96
4.45k
  void SetStreamAtIndex(uint32_t idx, const lldb::StreamSP &stream_sp) {
97
4.45k
    std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
98
    // Resize our stream vector as necessary to fit as many streams as needed.
99
    // This also allows this class to be used with hard coded indexes that can
100
    // be used contain many streams, not all of which are valid.
101
4.45k
    if (idx >= m_streams.size())
102
4.39k
      m_streams.resize(idx + 1);
103
4.45k
    m_streams[idx] = stream_sp;
104
4.45k
  }
105
106
protected:
107
  typedef std::vector<lldb::StreamSP> collection;
108
  mutable std::recursive_mutex m_streams_mutex;
109
  collection m_streams;
110
111
3.26M
  size_t WriteImpl(const void *s, size_t length) override {
112
3.26M
    std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
113
3.26M
    if (m_streams.empty())
114
0
      return 0;
115
116
3.26M
    size_t min_bytes_written = SIZE_MAX;
117
3.26M
    collection::iterator pos, end;
118
6.54M
    for (pos = m_streams.begin(), end = m_streams.end(); pos != end; 
++pos3.27M
) {
119
      // Allow for our collection to contain NULL streams. This allows the
120
      // StreamTee to be used with hard coded indexes for clients that might
121
      // want N total streams with only a few that are set to valid values.
122
3.27M
      Stream *strm = pos->get();
123
3.27M
      if (strm) {
124
3.27M
        const size_t bytes_written = strm->Write(s, length);
125
3.27M
        if (min_bytes_written > bytes_written)
126
3.26M
          min_bytes_written = bytes_written;
127
3.27M
      }
128
3.27M
    }
129
3.26M
    if (min_bytes_written == SIZE_MAX)
130
0
      return 0;
131
3.26M
    return min_bytes_written;
132
3.26M
  }
133
};
134
135
} // namespace lldb_private
136
137
#endif // LLDB_UTILITY_STREAMTEE_H