/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 |