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 | ConstString &GetBroadcasterClass() const override { |
222 | return GetStaticBroadcasterClass(); |
223 | } |
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 |
301 | |