LLDB mainline
ThreadedCommunication.h
Go to the documentation of this file.
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
15
16#include <atomic>
17#include <mutex>
18#include <string>
19
20#include <cstddef>
21#include <cstdint>
22
23namespace 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).
63
64public:
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);
208
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 ///
218
219 static llvm::StringRef GetStaticBroadcasterClass();
220
221 llvm::StringRef GetBroadcasterClass() const override {
223 }
224
225protected:
226 /// The read thread handle in case we need to cancel the thread.
227 /// @{
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.
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,
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
292private:
296};
297
298} // namespace lldb_private
299
300#endif // LLDB_CORE_THREADEDCOMMUNICATION_H
An event broadcasting class.
Definition: Broadcaster.h:146
An abstract communications class.
Definition: Communication.h:39
Communication()
Construct the Communication object.
An error handling class.
Definition: Status.h:44
"lldb/Core/ThreadedCommunication.h" Variation of Communication that supports threaded reads.
llvm::StringRef GetBroadcasterClass() const override
This needs to be filled in if you are going to register the broadcaster with the broadcaster manager ...
virtual void AppendBytesToCache(const uint8_t *src, size_t src_len, bool broadcast, lldb::ConnectionStatus status)
Append new bytes that get read from the read thread into the internal object byte cache.
const ThreadedCommunication & operator=(const ThreadedCommunication &)=delete
size_t Read(void *dst, size_t dst_len, const Timeout< std::micro > &timeout, lldb::ConnectionStatus &status, Status *error_ptr) override
Read bytes from the current connection.
void SetConnection(std::unique_ptr< Connection > connection) override
Sets the connection that it to be used by this class.
std::recursive_mutex m_bytes_mutex
A mutex to protect multi-threaded access to the cached bytes.
HostThread m_read_thread
The read thread handle in case we need to cancel the thread.
virtual bool StopReadThread(Status *error_ptr=nullptr)
Stops the read thread by cancelling it.
void SynchronizeWithReadThread()
Wait for the read thread to process all outstanding data.
std::atomic< bool > m_read_thread_did_exit
Whether the read thread is enabled.
lldb::ConnectionStatus m_pass_status
Connection status passthrough from read thread.
lldb::ConnectionStatus Disconnect(Status *error_ptr=nullptr) override
Disconnect the communications connection if one is currently connected.
void(* ReadThreadBytesReceived)(void *baton, const void *src, size_t src_len)
Status m_pass_error
Error passthrough from read thread.
virtual bool StartReadThread(Status *error_ptr=nullptr)
Starts a read thread whose sole purpose it to read bytes from the current connection.
std::atomic< bool > m_read_thread_enabled
Whether the read thread is enabled.
static llvm::StringRef GetStaticBroadcasterClass()
virtual bool JoinReadThread(Status *error_ptr=nullptr)
std::string m_bytes
A buffer to cache bytes read in the ReadThread function.
size_t GetCachedBytes(void *dst, size_t dst_len)
Get any available bytes from our data cache.
bool ReadThreadIsRunning()
Checks if there is a currently running read thread.
lldb::thread_result_t ReadThread()
The read thread function.
ThreadedCommunication(const ThreadedCommunication &)=delete
void SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived callback, void *callback_baton)
A class that represents a running process on the host machine.
void * thread_result_t
Definition: lldb-types.h:62
ConnectionStatus
Connection Status Types.