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