Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Core/ThreadedCommunication.h
Line
Count
Source (jump to first uncovered line)
1
//===-- ThreadedCommunication.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_CORE_THREADEDCOMMUNICATION_H
10
#define LLDB_CORE_THREADEDCOMMUNICATION_H
11
12
#include "lldb/Core/Communication.h"
13
#include "lldb/Host/HostThread.h"
14
#include "lldb/Utility/Broadcaster.h"
15
16
#include <atomic>
17
#include <mutex>
18
#include <string>
19
20
#include <cstddef>
21
#include <cstdint>
22
23
namespace lldb_private {
24
25
/// \class ThreadedCommunication ThreadedCommunication.h
26
/// "lldb/Core/ThreadedCommunication.h" Variation of Communication that
27
/// supports threaded reads.
28
///
29
/// ThreadedCommunication enhances the base Communication class with support
30
/// for multi-threaded mode.  In this mode, a read thread is spawned that
31
/// continually reads data and caches any received bytes. To start the read
32
/// thread clients call:
33
///
34
///     bool ThreadedCommunication::StartReadThread (Status *);
35
///
36
/// If true is returned a read thread has been spawned that will continually
37
/// execute a call to the pure virtual DoRead function:
38
///
39
///     size_t Communication::ReadFromConnection (void *, size_t, uint32_t);
40
///
41
/// When bytes are received the data gets cached in \a m_bytes and this class
42
/// will broadcast a \b eBroadcastBitReadThreadGotBytes event. Clients that
43
/// want packet based communication should override AppendBytesToCache. The
44
/// subclasses can choose to call the built in AppendBytesToCache with the \a
45
/// broadcast parameter set to false. This will cause the \b
46
/// eBroadcastBitReadThreadGotBytes event not get broadcast, and then the
47
/// subclass can post a \b eBroadcastBitPacketAvailable event when a full
48
/// packet of data has been received.
49
///
50
/// If the connection is disconnected a \b eBroadcastBitDisconnected event
51
/// gets broadcast. If the read thread exits a \b
52
/// eBroadcastBitReadThreadDidExit event will be broadcast. Clients can also
53
/// post a \b eBroadcastBitReadThreadShouldExit event to this object which
54
/// will cause the read thread to exit.
55
///
56
/// ThreadedCommunication inherits from Broadcaster which means it can be used
57
/// in conjunction with Listener to wait for multiple broadcaster objects and
58
/// multiple events from each of those objects. ThreadedCommunication defines a
59
/// set of pre-defined event bits (see enumerations definitions that start with
60
/// "eBroadcastBit" below).
61
class ThreadedCommunication : public Communication, public Broadcaster {
62
  using Communication::Communication;
63
64
public:
65
  FLAGS_ANONYMOUS_ENUM(){
66
      eBroadcastBitDisconnected =
67
          (1u << 0), ///< Sent when the communications connection is lost.
68
      eBroadcastBitReadThreadGotBytes =
69
          (1u << 1), ///< Sent by the read thread when bytes become available.
70
      eBroadcastBitReadThreadDidExit =
71
          (1u
72
           << 2), ///< Sent by the read thread when it exits to inform clients.
73
      eBroadcastBitReadThreadShouldExit =
74
          (1u << 3), ///< Sent by clients that need to cancel the read thread.
75
      eBroadcastBitPacketAvailable =
76
          (1u << 4), ///< Sent when data received makes a complete packet.
77
      eBroadcastBitNoMorePendingInput = (1u << 5), ///< Sent by the read thread
78
                                                   /// to indicate all pending
79
                                                   /// input has been processed.
80
  };
81
82
  typedef void (*ReadThreadBytesReceived)(void *baton, const void *src,
83
                                          size_t src_len);
84
85
  /// Construct the ThreadedCommunication object with the specified name for the
86
  /// Broadcaster that this object inherits from.
87
  ///
88
  /// \param[in] broadcaster_name
89
  ///     The name of the broadcaster object.  This name should be as
90
  ///     complete as possible to uniquely identify this object. The
91
  ///     broadcaster name can be updated after the connect function
92
  ///     is called.
93
  ThreadedCommunication(const char *broadcaster_name);
94
95
  /// Destructor.
96
  ///
97
  /// The destructor is virtual since this class gets subclassed.
98
  ~ThreadedCommunication() override;
99
100
  void Clear() override;
101
102
  /// Disconnect the communications connection if one is currently connected.
103
  ///
104
  /// \return
105
  ///     \b True if the disconnect succeeded, \b false otherwise. The
106
  ///     internal error object should be filled in with an
107
  ///     appropriate value based on the result of this function.
108
  ///
109
  /// \see Status& Communication::GetError ();
110
  /// \see bool Connection::Disconnect ();
111
  lldb::ConnectionStatus Disconnect(Status *error_ptr = nullptr) override;
112
113
  /// Read bytes from the current connection.
114
  ///
115
  /// If no read thread is running, this function call the connection's
116
  /// Connection::Read(...) function to get any available.
117
  ///
118
  /// If a read thread has been started, this function will check for any
119
  /// cached bytes that have already been read and return any currently
120
  /// available bytes. If no bytes are cached, it will wait for the bytes to
121
  /// become available by listening for the \a eBroadcastBitReadThreadGotBytes
122
  /// event. If this function consumes all of the bytes in the cache, it will
123
  /// reset the \a eBroadcastBitReadThreadGotBytes event bit.
124
  ///
125
  /// \param[in] dst
126
  ///     A destination buffer that must be at least \a dst_len bytes
127
  ///     long.
128
  ///
129
  /// \param[in] dst_len
130
  ///     The number of bytes to attempt to read, and also the max
131
  ///     number of bytes that can be placed into \a dst.
132
  ///
133
  /// \param[in] timeout
134
  ///     A timeout value or std::nullopt for no timeout.
135
  ///
136
  /// \return
137
  ///     The number of bytes actually read.
138
  ///
139
  /// \see size_t Connection::Read (void *, size_t);
140
  size_t Read(void *dst, size_t dst_len, const Timeout<std::micro> &timeout,
141
              lldb::ConnectionStatus &status, Status *error_ptr) override;
142
143
  /// Sets the connection that it to be used by this class.
144
  ///
145
  /// By making a communication class that uses different connections it
146
  /// allows a single communication interface to negotiate and change its
147
  /// connection without any interruption to the client. It also allows the
148
  /// Communication class to be subclassed for packet based communication.
149
  ///
150
  /// \param[in] connection
151
  ///     A connection that this class will own and destroy.
152
  ///
153
  /// \see
154
  ///     class Connection
155
  void SetConnection(std::unique_ptr<Connection> connection) override;
156
157
  /// Starts a read thread whose sole purpose it to read bytes from the
158
  /// current connection. This function will call connection's read function:
159
  ///
160
  /// size_t Connection::Read (void *, size_t);
161
  ///
162
  /// When bytes are read and cached, this function will call:
163
  ///
164
  /// Communication::AppendBytesToCache (const uint8_t * bytes, size_t len,
165
  /// bool
166
  /// broadcast);
167
  ///
168
  /// Subclasses should override this function if they wish to override the
169
  /// default action of caching the bytes and broadcasting a \b
170
  /// eBroadcastBitReadThreadGotBytes event.
171
  ///
172
  /// \return
173
  ///     \b True if the read thread was successfully started, \b
174
  ///     false otherwise.
175
  ///
176
  /// \see size_t Connection::Read (void *, size_t);
177
  /// \see void Communication::AppendBytesToCache (const uint8_t * bytes,
178
  ///                                              size_t len, bool broadcast);
179
  virtual bool StartReadThread(Status *error_ptr = nullptr);
180
181
  /// Stops the read thread by cancelling it.
182
  ///
183
  /// \return
184
  ///     \b True if the read thread was successfully canceled, \b
185
  ///     false otherwise.
186
  virtual bool StopReadThread(Status *error_ptr = nullptr);
187
188
  virtual bool JoinReadThread(Status *error_ptr = nullptr);
189
  /// Checks if there is a currently running read thread.
190
  ///
191
  /// \return
192
  ///     \b True if the read thread is running, \b false otherwise.
193
  bool ReadThreadIsRunning();
194
195
  /// The read thread function. This function will call the "DoRead"
196
  /// function continuously and wait for data to become available. When data
197
  /// is received it will append the available data to the internal cache and
198
  /// broadcast a \b eBroadcastBitReadThreadGotBytes event.
199
  ///
200
  /// \param[in] comm_ptr
201
  ///     A pointer to an instance of this class.
202
  ///
203
  /// \return
204
  ///     \b NULL.
205
  ///
206
  /// \see void Communication::ReadThreadGotBytes (const uint8_t *, size_t);
207
  lldb::thread_result_t ReadThread();
208
209
  void SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived callback,
210
                                          void *callback_baton);
211
212
  /// Wait for the read thread to process all outstanding data.
213
  ///
214
  /// After this function returns, the read thread has processed all data that
215
  /// has been waiting in the Connection queue.
216
  ///
217
  void SynchronizeWithReadThread();
218
219
  static ConstString &GetStaticBroadcasterClass();
220
221
0
  ConstString &GetBroadcasterClass() const override {
222
0
    return GetStaticBroadcasterClass();
223
0
  }
224
225
protected:
226
  /// The read thread handle in case we need to cancel the thread.
227
  /// @{
228
  HostThread m_read_thread;
229
  std::mutex m_read_thread_mutex;
230
  /// @}
231
232
  /// Whether the read thread is enabled. This cannot be guarded by the read
233
  /// thread mutex becuase it is used as the control variable to exit the read
234
  /// thread.
235
  std::atomic<bool> m_read_thread_enabled;
236
237
  /// Whether the read thread is enabled. Technically this could be guarded by
238
  /// the read thread mutex but that needlessly complicates things to
239
  /// check this variables momentary value.
240
  std::atomic<bool> m_read_thread_did_exit;
241
242
  std::string
243
      m_bytes; ///< A buffer to cache bytes read in the ReadThread function.
244
  std::recursive_mutex m_bytes_mutex;   ///< A mutex to protect multi-threaded
245
                                        /// access to the cached bytes.
246
  lldb::ConnectionStatus m_pass_status; ///< Connection status passthrough
247
                                        /// from read thread.
248
  Status m_pass_error;                  ///< Error passthrough from read thread.
249
  std::mutex m_synchronize_mutex;
250
  ReadThreadBytesReceived m_callback;
251
  void *m_callback_baton;
252
253
  /// Append new bytes that get read from the read thread into the internal
254
  /// object byte cache. This will cause a \b eBroadcastBitReadThreadGotBytes
255
  /// event to be broadcast if \a broadcast is true.
256
  ///
257
  /// Subclasses can override this function in order to inspect the received
258
  /// data and check if a packet is available.
259
  ///
260
  /// Subclasses can also still call this function from the overridden method
261
  /// to allow the caching to correctly happen and suppress the broadcasting
262
  /// of the \a eBroadcastBitReadThreadGotBytes event by setting \a broadcast
263
  /// to false.
264
  ///
265
  /// \param[in] src
266
  ///     A source buffer that must be at least \a src_len bytes
267
  ///     long.
268
  ///
269
  /// \param[in] src_len
270
  ///     The number of bytes to append to the cache.
271
  virtual void AppendBytesToCache(const uint8_t *src, size_t src_len,
272
                                  bool broadcast,
273
                                  lldb::ConnectionStatus status);
274
275
  /// Get any available bytes from our data cache. If this call empties the
276
  /// data cache, the \b eBroadcastBitReadThreadGotBytes event will be reset
277
  /// to signify no more bytes are available.
278
  ///
279
  /// \param[in] dst
280
  ///     A destination buffer that must be at least \a dst_len bytes
281
  ///     long.
282
  ///
283
  /// \param[in] dst_len
284
  ///     The number of bytes to attempt to read from the cache,
285
  ///     and also the max number of bytes that can be placed into
286
  ///     \a dst.
287
  ///
288
  /// \return
289
  ///     The number of bytes extracted from the data cache.
290
  size_t GetCachedBytes(void *dst, size_t dst_len);
291
292
private:
293
  ThreadedCommunication(const ThreadedCommunication &) = delete;
294
  const ThreadedCommunication &
295
  operator=(const ThreadedCommunication &) = delete;
296
};
297
298
} // namespace lldb_private
299
300
#endif // LLDB_CORE_THREADEDCOMMUNICATION_H