ALib C++ Library
Library Version: 2511 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
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 \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 running or at least started.
264 bool IsAlive() { return state == State::Started || state == State::Running; }
265
266 /// Starts the execution of the thread. Method #Run is invoked by the new system thread,
267 /// which - if not overwritten - invokes the method \alib{threads;Runnable::Run}.
268 /// Of course, this method immediately returns, and after invocation, method #IsAlive will
269 /// usually return \c true (unless the executed thread is not finished already).
271 virtual void Start();
272
273 /// Terminates a thread using <c>std::join()</c>.
274 /// When this method is called, the thread's state should be <b>State::Done</b>, which
275 /// is the case after method \b Run has exited.
276 /// Otherwise, a \ref alib_mod_assert "warning is raised".
278 virtual void Join();
279
280
281 //################################################################################################
282 // Static interface
283 //################################################################################################
284 public:
285 #if ( !defined(_MSC_VER) && !defined( ALIB_API_NO_DLL ) ) || DOXYGEN
286 /// Static method that returns an object representing the thread that invoked this call.
287 /// If no instance of class \b %Thread was created for the current thread, yet, then one
288 /// with a negative ID is created, indicating that this thread was not created by \alib.
289 ///
290 /// Once a \b %Thread was created, a pointer to this instance stored in the <c>thread_local</c>
291 /// namespace variable \alib{threads;THIS_THREAD} is returned.
292 /// Thus, this method is very fast from, starting with the second invocation.
293 ///
294 /// \note For technical reasons, under WindowsOS and DLL compilation, this method is \b not
295 /// inlined, but implemented using the macro \ref ALIB_DLL.
296 /// @return A pointer to the current thread.
297 static inline
299 if (THIS_THREAD == nullptr )
300 THIS_THREAD= Get( std::this_thread::get_id() );
301 return THIS_THREAD;
302 }
303 #else
304 static ALIB_DLL
306 #endif
307
308 /// Static method that returns an object representing the thread identified by the given
309 /// system ID \p{nativeID}. \c nullptr is returned only if:
310 /// - parameter \p{nativeID} is nulled, or
311 /// - during \ref alib_mod_bs "bootstrapping of ALib", which multithreaded
312 /// applications have to perform before starting threads, \c nullptr might be returned as
313 /// well.
314 ///
315 /// In any other situations, either,
316 /// - \p{nativeID} is received from a thread that was started using this class \b Thread, then
317 /// a pointer to that instance is returned, or
318 /// - the thread was started without the use of \alib, then an instance of this class is
319 /// created (once) and registered.
320 ///
321 /// @param nativeID The C++ Standard Libraray identifier.
322 /// @return A pointer to the instance associated with the native thread ID.
324 static Thread* Get(std::thread::id nativeID);
325
326 /// Static method that returns the thread that initialized the library.
327 /// Such thread is supposedly the "main" thread, as bootstrapping usually is performed
328 /// by the process before any other threads are started.
329 /// @return A pointer to the main thread.
331 static Thread* GetMain();
332 #endif // !ALIB_SINGLE_THREADED
333
334
335 /// Proactively offers the system to suspend the current thread.
336 /// Invokes <c>std::this_thread::yield</c>.
337 /// \note Must not be named 'Yield', because this is a macro name with MSVC.
338 static
339 void YieldToSystem() { std::this_thread::yield(); }
340
341 /// Suspends the current thread by calling <em>std::this_thread::sleep_for</em>.
342 /// \see Variants #SleepMicros, #SleepNanos, #Sleep and #SleepUntil
343 /// @param milliseconds Sleep time in milliseconds.
344 static void SleepMillis ( int milliseconds )
345 { std::this_thread::sleep_for( std::chrono::milliseconds( milliseconds ) ); }
346
347
348 /// Suspends the current thread by calling <em>std::this_thread::sleep_for</em>.
349 /// \see Variants #SleepMillis, #SleepNanos, #Sleep and #SleepUntil
350 /// @param microseconds Sleep time in microseconds.
351 static void SleepMicros ( int64_t microseconds )
352 { std::this_thread::sleep_for( std::chrono::microseconds( microseconds ) ); }
353
354 /// Suspends the current thread by calling <em>std::this_thread::sleep_for</em>.
355 /// \see Variants #SleepMicros, #SleepMillis, #Sleep and #SleepUntil
356 /// @param nanoseconds Sleep time in nanoseconds.
357 static void SleepNanos ( int64_t nanoseconds )
358 { std::this_thread::sleep_for( std::chrono::nanoseconds( nanoseconds ) ); }
359
360 /// Suspends the current thread by calling <em>std::this_thread::sleep_for</em>.
361 /// \see Variants #SleepUntil, #SleepMicros, #SleepMillis and #SleepNanos.
362 /// @param duration Sleep duration.
363 static void Sleep ( const Ticks::Duration& duration )
364 { std::this_thread::sleep_for( duration.Export() ); }
365
366 /// Suspends the current thread by calling <em>std::this_thread::sleep_for</em>.
367 /// \see Variants #SleepUntil, #SleepMicros, #SleepMillis and #SleepNanos.
368 /// @param duration Sleep duration.
369 static void Sleep ( const Ticks::Duration::TDuration& duration )
370 { std::this_thread::sleep_for( duration ); }
371
372 /// Suspends the current thread by calling <em>std::this_thread::sleep_for</em>.
373 /// \see Variants #Sleep, #SleepMicros, #SleepMillis and #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 \b alib.
384#endif
385
386/// Type alias in namespace \b alib.
388
389/// Type to store thread identifiers.
391
392} // namespace [alib]
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:298
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:344
static void Sleep(const Ticks::Duration::TDuration &duration)
Definition thread.inl:369
static void SleepNanos(int64_t nanoseconds)
Definition thread.inl:357
static void Sleep(const Ticks::Duration &duration)
Definition thread.inl:363
static void YieldToSystem()
Definition thread.inl:339
ThreadID GetID() const
Definition thread.inl:227
static void SleepMicros(int64_t microseconds)
Definition thread.inl:351
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:285
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:225
virtual ALIB_DLL void Join()
Definition thread.cpp:244
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:375
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:313
static ALIB_DLL Thread * Get(std::thread::id nativeID)
Definition thread.cpp:314
#define ALIB_DLL
Definition alib.inl:503
#define A_CHAR(STR)
#define ALIB_EXPORT
Definition alib.inl:497
Details of namespace alib::threads.
Definition thread.cpp:108
void threadStart(Thread *thread)
Definition thread.cpp:110
void BootstrapThreadMap(integer qty)
Definition thread.cpp:130
integer ThreadID
The ALib thread identifier type.
Definition thread.inl:23
void bootstrap()
Definition thread.cpp:137
thread_local Thread * THIS_THREAD
A thread-local pointer to the ALib representation of the actual thread.
Definition thread.cpp:215
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:160
threads::ThreadID ThreadID
Type to store thread identifiers.
Definition thread.inl:390
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:387
threads::Runnable Runnable
Type alias in namespace alib.
Definition thread.inl:383
time::Ticks Ticks
Type alias in namespace alib.
Definition ticks.inl:79
characters::character character
Type alias in namespace alib.
ALIB_DLL void Shutdown()