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