ALib C++ Library
Library Version: 2412 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
thread.hpp
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header file is part of module \alib_threads of the \aliblong.
4///
5/// \emoji :copyright: 2013-2024 A-Worx GmbH, Germany.
6/// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8#ifndef HPP_ALIB_THREADS_THREAD
9#define HPP_ALIB_THREADS_THREAD 1
10#pragma once
11#if !defined(DOXYGEN)
12# include "alib/alib.hpp"
13#endif
14ALIB_ASSERT_MODULE(THREADS)
15
16#include "alib/strings/astring.hpp"
17#include "alib/time/ticks.hpp"
18#if ALIB_ENUMS
19# include "alib/enums/records.hpp"
20#endif
21#include <thread>
22
23namespace alib { namespace threads {
24
25// forwards
26class Thread;
27namespace detail
28{
29 void threadStart( Thread* t );
30}
31
32
33/// The ALib thread identifier type
34using ThreadID= integer;
35
36//==================================================================================================
37/// This is a value that may be passed as a value indicating an undefined thread
38//==================================================================================================
39static constexpr ThreadID UNDEFINED = 0;
40
41
42//==================================================================================================
43/// Initializes \alib thread logic.
44/// Multiple invocations of this method are forbidden.
45///
46/// The \ref alib_manual_bootstrapping "standard bootstrap" code of \alib, hence the (overloaded)
47/// functions \ref alib::Bootstrap will call this function.
48///
49/// \see
50/// For information about using this method, consult chapter
51/// \ref alib_manual_bootstrapping_nocamps of the \ref alib_manual.
52//==================================================================================================
54void Bootstrap();
55
56//==================================================================================================
57/// Frees resources and shuts down \alib thread logic.
58/// Multiple invocations of this method are forbidden.
59/// The \ref alib_manual_bootstrapping "standard bootstrap" code of \alib, hence the (overloaded)
60/// functions \ref alib::Shutdown will call this function.
61///
62/// \see
63/// Sibling function \alib{threads;Bootstrap}.
64//==================================================================================================
66void Shutdown();
67
68//==================================================================================================
69/// This is a virtual abstract (interface) type that provides the executable method
70/// for an associated \alib{threads;Thread}.
71///
72/// Objects of this type may be passed to the constructor of class \alib{threads;Thread}. The
73/// default implementation of method \alib{threads;Thread::Run} will then invoke
74/// method #Run of this class.
75//==================================================================================================
77{
78 public:
79 /// Virtual destructor.
80 virtual ~Runnable() {}
81
82 /// The method invoked by the default implementation of \alib{threads;Thread::Run}
83 /// of the thread object that this runnable is associated with.
84 virtual void Run() = 0;
85};
86
87//==================================================================================================
88/// This class provides a limited (minimal) abstraction of C++ type <c>std::thread</c>.
89/// As elaborated in the module's documentation, this class is not considered full featured
90/// but - as of today- is meant for simple use cases only.
91///
92/// For general information of multi-threading support provided by \alib, please consult
93/// the \ref alib_mod_threads.
94///
95/// ## Friends ##
96/// function \alib{threads;Bootstrap}
97/// function \alib{threads;Shutdown}
98/// @see
99/// For this class, a \ref alibtools_debug_helpers_gdb "pretty printer" for the
100/// GNU debugger is provided.
101//==================================================================================================
102class Thread : public Runnable
103{
104 #if !DOXYGEN
105 friend void ALIB_API Bootstrap ();
106 friend void ALIB_API Shutdown ();
107 friend void detail::threadStart( Thread* t );
108 #endif
109
110 public:
111 /// States that follow lifecycle of the thread. The states are accessible with method
112 /// #GetState.
113 enum class State
114 {
115 Unstarted = 0 ///< Not started and no call to #Start was performed, yet.
116 ///< This is the state after construction of an instance.
117 ,Started = 1 ///< Method #Start was invoked but not running, yet.
118 ,Running = 2 ///< The thread's #Run method is currently processed.
119 ,Done = 3 ///< The run method is processed, and the thread is ready to be
120 ///< terminated.
121 ,Terminated = 4 ///< The thread is terminated.
122 };
123
124 // ###############################################################################################
125 // Protected fields
126 // ###############################################################################################
127 protected:
128 /// The internal C++ thread object.
129 std::thread* c11Thread =nullptr;
130
131 /// The internal C++ thread id.
132 std::thread::id nativeID;
133
134 /// The runnable to execute.
136
137 /// The id of the thread.
138 ThreadID id =0;
139
140 /// The name of the thread.
142
143 /// Internal flag to indicate if the thread is alive.
145
146
147 // ###############################################################################################
148 // Constructors, destructor
149 // ###############################################################################################
150 public:
151 //==============================================================================================
152 /// Constructor without a parameter specifying a Runnable. Such thread will not execute any
153 /// code unless a specialized class is derived that overrides virtual method #Run.
154 ///
155 /// @param pName (Optional) The designated name of the thread. If the name provided is,
156 /// empty the name of the thread will be set to match a string representation
157 /// of the thread id.
158 //==============================================================================================
160 Thread( const String& pName= EMPTY_STRING )
161 : Thread( nullptr, pName ) {}
162
163 //==============================================================================================
164 /// Constructor with provision of a Runnable 'target'. The Run method of 'target' will be
165 /// executed upon thread start, unless this class is specialized an its own Run() method is
166 /// overwritten.
167 /// @param target The target to execute when the thread runs.
168 /// @param pName (Optional) The designated name of the thread. If the name provided is,
169 /// empty the name of the thread will be set to match a string representation
170 /// of the thread id.
171 //==============================================================================================
172 ALIB_API Thread(Runnable* target, const String& pName= EMPTY_STRING );
173
174
175 //==============================================================================================
176 /// Before destruction, #Join has to be called.
177 /// The destructor blocks if the thread was started and is still running.
178 /// Blocking lasts until the thread's end of execution.<br>
179 //==============================================================================================
180 ALIB_API virtual ~Thread() override;
181
182 /// Deleted copy constructor.
183 Thread(const Thread& ) = delete;
184
185
186 // #############################################################################################
187 // Runnable Interface implementation
188 // #############################################################################################
189
190 /// If we have a runnable, its \b run() method is executed. Otherwise nothing is done.
191 ///
192 /// Hence, to have the thread execute something, either a \alib{threads;Runnable}
193 /// has to be provided or a derived version of this class replaces this method.
194 ///
195 virtual void Run() override { if (runnable) runnable->Run(); }
196
197 // ###############################################################################################
198 // Interface
199 // ###############################################################################################
200
201 //==============================================================================================
202 /// Returns the id of this Thread. Systems threads have IDs below 0, ALIB generated threads
203 /// have positive IDs and start with 1.
204 ///
205 /// @return The \alib id of the thread.
206 //==============================================================================================
207 ThreadID GetID() const { return id; }
208
209 //==============================================================================================
210 /// Returns the id of this Thread. Systems threads have IDs below 0, ALIB generated threads
211 /// have positive IDs and start with 1.
212 ///
213 /// @return The \alib id of the thread.
214 //==============================================================================================
215 std::thread::id GetNativeID() const { return nativeID; }
216
217 //==============================================================================================
218 /// Returns the name of the thread. An \alib thread can have any name that is given to it and
219 /// such name can be changed any time. In fact, names are for debugging and logging
220 /// purposes only.
221 ///
222 /// @return Returns the name of the thread.
223 //==============================================================================================
224 virtual
225 const CString GetName() const { return name; }
226
227 //==============================================================================================
228 /// Sets the name of the thread. An \alib thread can have any name that is given to it and
229 /// such name can be changed any time.
230 /// Thread names are meant for debugging and logging purposes only.
231 /// @param newName The name that the Thread should hold.
232 //==============================================================================================
233 virtual void SetName( const String& newName ) { name.Reset( newName); }
234
235 //==============================================================================================
236 /// Returns the state of the thread. The states are given in enumeration #State and
237 /// during the lifecycle of the thread, the state transitions from
238 /// \alib{threads::Thread;State::Unstarted} to \alib{threads::Thread;State::Terminated}.
239 /// \note
240 /// For system threads (the thread that executed function <c>main thread</c> and those
241 /// not created using \alib thread features) \alib{threads::Thread;State::Running} is
242 /// returned.
243 /// For those, it can't be determined if the thread is stared, alive or not.
244 /// @return The current state within the thread's lifecycle.
245 //==============================================================================================
246 State GetState() { return state; }
247
248 //==============================================================================================
249 /// A shortcut to
250 /// <c>GetState().first == State::Started || GetState().first == State::Running</c>.
251 ///
252 /// @return \c true if the current state of the thread is
253 /// \alib{threads;Thread;State::Running}.
254 //==============================================================================================
255 bool IsAlive() { return state == State::Started
256 || state == State::Running; }
257
258 //==============================================================================================
259 /// Starts the execution of the thread. Method #Run is invoked by the new system thread,
260 /// which - if not overwritten - invokes the method \alib{threads;Runnable::Run}.
261 /// Of course, this method immediately returns, and after invocation, method #IsAlive will
262 /// usually return \c true (unless the executed thread is not finished already).
263 //==============================================================================================
265 virtual void Start();
266
267 //==============================================================================================
268 /// Terminates a thread using <c>std::join()</c>.
269 /// When this method is called, the thread should be in state <b>State::Done</b>, which
270 /// is the case after method \b Run has exited.
271 /// Otherwise, an \alib warning is raised.
272 //==============================================================================================
274 virtual void Join();
275
276 // ###############################################################################################
277 // Static interface
278 // ###############################################################################################
279 public:
280 /// Static method that returns an object representing the thread that invoked this call.
281 /// @return A pointer to the current thread.
282 static
283 Thread* GetCurrent() { return Get( std::this_thread::get_id() ); }
284
285 /// Static method that returns an object representing the thread identified by the given
286 /// system ID \p{nativeID}. \c nullptr is returned only if:
287 /// - parameter \p{nativeID} is nulled, or
288 /// - during \ref alib_manual_bootstrapping "bootstrapping of ALib", which multithreaded
289 /// applications have to perform before starting threads, \c nullptr might be returned as
290 /// well.
291 ///
292 /// In any other situations, either,
293 /// - \p{nativeID} is received from a thread that was started using this class \b Thread, then
294 /// a pointer to that instance is returned, or
295 /// - the thread was started without the use of \alib, then an instance of this class is
296 /// created (once) and registered.
297 ///
298 /// @param nativeID The C++ Standard Libraray identifier.
299 /// @return A pointer to the instance associated with the native thread ID.
300 static
302 Thread* Get(std::thread::id nativeID);
303
304 //==============================================================================================
305 /// Static method that returns the thread that initialized the library.
306 /// Such thread this is supposedly the "main" thread as bootstrapping usually is performed
307 /// by the process before any other threads are started.
308 ///
309 /// @return A pointer to the main thread.
310 //==============================================================================================
311 ALIB_API static
312 Thread* GetMain();
313
314 //==============================================================================================
315 /// Proactively offers the system to suspend the current thread.
316 /// Invokes <c>std::this_thread::yield</c>.
317 /// \note Must not be named 'Yield', because this is a macro name with MSVC.
318 //==============================================================================================
319 static
320 void YieldToSystem() { std::this_thread::yield(); }
321
322 /// Suspends the current thread by calling <em>std::this_thread::sleep_for</em>.
323 /// \see Variants #SleepMicros, #SleepNanos, #Sleep and #SleepUntil
324 /// @param milliseconds Sleep time in milliseconds.
325 static void SleepMillis ( int milliseconds )
326 { std::this_thread::sleep_for( std::chrono::milliseconds( milliseconds ) ); }
327
328
329 /// Suspends the current thread by calling <em>std::this_thread::sleep_for</em>.
330 /// \see Variants #SleepMillis, #SleepNanos, #Sleep and #SleepUntil
331 /// @param microseconds Sleep time in microseconds.
332 static void SleepMicros ( int64_t microseconds )
333 { std::this_thread::sleep_for( std::chrono::microseconds( microseconds ) ); }
334
335 /// Suspends the current thread by calling <em>std::this_thread::sleep_for</em>.
336 /// \see Variants #SleepMicros, #SleepMillis, #Sleep and #SleepUntil
337 /// @param nanoseconds Sleep time in nanoseconds.
338 static void SleepNanos ( int64_t nanoseconds )
339 { std::this_thread::sleep_for( std::chrono::nanoseconds( nanoseconds ) ); }
340
341 /// Suspends the current thread by calling <em>std::this_thread::sleep_for</em>.
342 /// \see Variants #SleepUntil, #SleepMicros, #SleepMillis and #SleepNanos.
343 /// @param duration Sleep duration.
344 static void Sleep ( const Ticks::Duration& duration )
345 { std::this_thread::sleep_for( duration.Export() ); }
346
347 /// Suspends the current thread by calling <em>std::this_thread::sleep_for</em>.
348 /// \see Variants #SleepUntil, #SleepMicros, #SleepMillis and #SleepNanos.
349 /// @param duration Sleep duration.
350 static void Sleep ( const Ticks::Duration::TDuration& duration )
351 { std::this_thread::sleep_for( duration ); }
352
353 /// Suspends the current thread by calling <em>std::this_thread::sleep_for</em>.
354 /// \see Variants #Sleep, #SleepMicros, #SleepMillis and #SleepNanos
355 /// @param time Sleep duration.
356 static void SleepUntil ( const Ticks& time )
357 { std::this_thread::sleep_until( time.Export() ); }
358}; // class Thread
359
360#if ALIB_BOXING && !DOXYGEN
361inline
362void FAppend_thread(const boxing::Box& self, strings::TAString<character,lang::HeapAllocator>& target ) {
363 const Thread* src= self.Unbox<Thread*>();
364 if ( src )
365 target << src;
366 else
367 target << "nullptr";
368}
369#endif
370
371
372
373} // namespace alib[::threads]
374
375/// Type alias in namespace \b alib.
377
378/// Type alias in namespace \b alib.
380
381/// Type to store thread identifiers.
383
384
385
386} // namespace [alib]
387
392
393#if ALIB_ENUMS && ALIB_BOXING
395#endif
396
397
398#endif // HPP_ALIB_THREADS_THREAD
399
const TUnboxable Unbox() const
virtual ~Runnable()
Virtual destructor.
Definition thread.hpp:80
virtual void Run()=0
virtual ALIB_API void Start()
Definition thread.cpp:284
static void YieldToSystem()
Definition thread.hpp:320
ThreadID id
The id of the thread.
Definition thread.hpp:138
static Thread * GetCurrent()
Definition thread.hpp:283
virtual void SetName(const String &newName)
Definition thread.hpp:233
static void SleepUntil(const Ticks &time)
Definition thread.hpp:356
static void Sleep(const Ticks::Duration::TDuration &duration)
Definition thread.hpp:350
virtual ALIB_API ~Thread() override
Definition thread.cpp:206
virtual const CString GetName() const
Definition thread.hpp:225
@ Running
The thread's Run method is currently processed.
@ Started
Method Start was invoked but not running, yet.
@ Terminated
The thread is terminated.
ThreadID GetID() const
Definition thread.hpp:207
Thread(const Thread &)=delete
Deleted copy constructor.
AString name
The name of the thread.
Definition thread.hpp:141
State state
Internal flag to indicate if the thread is alive.
Definition thread.hpp:144
std::thread * c11Thread
The internal C++ thread object.
Definition thread.hpp:129
static void SleepNanos(int64_t nanoseconds)
Definition thread.hpp:338
static ALIB_API Thread * GetMain()
Definition thread.cpp:320
ALIB_API Thread(const String &pName=EMPTY_STRING)
Definition thread.hpp:160
virtual void Run() override
Definition thread.hpp:195
static ALIB_API Thread * Get(std::thread::id nativeID)
Definition thread.cpp:321
static void SleepMicros(int64_t microseconds)
Definition thread.hpp:332
virtual ALIB_API void Join()
Definition thread.cpp:220
std::thread::id GetNativeID() const
Definition thread.hpp:215
std::thread::id nativeID
The internal C++ thread id.
Definition thread.hpp:132
static void SleepMillis(int milliseconds)
Definition thread.hpp:325
Runnable * runnable
The runnable to execute.
Definition thread.hpp:135
static void Sleep(const Ticks::Duration &duration)
Definition thread.hpp:344
TTimePoint Export() const
#define ALIB_ASSERT_MODULE(modulename)
Definition alib.hpp:223
#define ALIB_STRINGS_APPENDABLE_TYPE_N(TYPE)
Definition tastring.inl:147
#define ALIB_ENUMS_ASSIGN_RECORD(TEnum, TRecord)
Definition records.hpp:712
#define ALIB_API
Definition alib.hpp:639
#define ALIB_STRINGS_APPENDABLE_TYPE_W(TYPE)
Definition tastring.inl:154
void threadStart(Thread *thread)
Definition thread.cpp:73
void Bootstrap()
Definition thread.cpp:93
static constexpr ThreadID UNDEFINED
This is a value that may be passed as a value indicating an undefined thread.
Definition thread.hpp:39
integer ThreadID
The ALib thread identifier type.
Definition loxpimpl.inl:28
void Shutdown()
Definition thread.cpp:133
Definition alib.cpp:69
threads::Thread Thread
Type alias in namespace alib.
Definition thread.hpp:379
constexpr const String EMPTY_STRING
An empty string of the default character type.
Definition string.hpp:2529
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:273
threads::ThreadID ThreadID
Type to store thread identifiers.
Definition thread.hpp:382