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