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