Coverage Report

Created: 2026-08-11 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/poco/Foundation/include/Poco/Thread.h
Line
Count
Source
1
//
2
// Thread.h
3
//
4
// Library: Foundation
5
// Package: Threading
6
// Module:  Thread
7
//
8
// Definition of the Thread class.
9
//
10
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
11
// and Contributors.
12
//
13
// SPDX-License-Identifier: BSL-1.0
14
//
15
16
17
#ifndef Foundation_Thread_INCLUDED
18
#define Foundation_Thread_INCLUDED
19
20
21
#include "Poco/Foundation.h"
22
#include "Poco/Event.h"
23
#include "Poco/Mutex.h"
24
#include <thread>
25
#include <chrono>
26
27
28
#if defined(POCO_OS_FAMILY_WINDOWS)
29
#include "Poco/Thread_WIN32.h"
30
#elif defined(POCO_VXWORKS)
31
#include "Poco/Thread_VX.h"
32
#else
33
#include "Poco/Thread_POSIX.h"
34
#endif
35
36
37
namespace Poco {
38
39
40
class Runnable;
41
class ThreadLocalStorage;
42
43
44
class Foundation_API Thread: private ThreadImpl
45
  /// This class implements a platform-independent
46
  /// wrapper to an operating system thread.
47
  ///
48
  /// Every Thread object gets a unique (within
49
  /// its process) numeric thread ID.
50
  /// Furthermore, a thread can be assigned a name.
51
  /// The name of a thread can be changed at any time.
52
{
53
public:
54
  using TID = ThreadImpl::TIDImpl;
55
56
  using ThreadImpl::Callable;
57
58
  enum Priority
59
    /// Thread priorities.
60
  {
61
    PRIO_LOWEST  = PRIO_LOWEST_IMPL, /// The lowest thread priority.
62
    PRIO_LOW     = PRIO_LOW_IMPL,    /// A lower than normal thread priority.
63
    PRIO_NORMAL  = PRIO_NORMAL_IMPL, /// The normal thread priority.
64
    PRIO_HIGH    = PRIO_HIGH_IMPL,   /// A higher than normal thread priority.
65
    PRIO_HIGHEST = PRIO_HIGHEST_IMPL /// The highest thread priority.
66
  };
67
68
  enum Policy
69
  {
70
    POLICY_DEFAULT = POLICY_DEFAULT_IMPL
71
  };
72
73
  Thread(uint32_t sigMask = 0);
74
    /// Creates a thread. Call start() to start it.
75
    ///
76
    /// The optional sigMask parameter specifies which signals should be blocked.
77
    /// To block a specific signal, set the corresponding bit in the sigMask.
78
    /// Multiple bits can be set in the mask to block multiple signals if needed.
79
    ///
80
    /// Available on POSIX platforms only
81
82
  Thread(const std::string& name, uint32_t sigMask = 0);
83
    /// Creates a named thread. Call start() to start it.
84
    ///
85
    /// The optional sigMask parameter specifies which signals should be blocked.
86
    /// To block a specific signal, set the corresponding bit in the sigMask.
87
    /// Multiple bits can be set in the mask to block multiple signals if needed.
88
    ///
89
    /// Available on POSIX platforms only
90
91
  ~Thread();
92
    /// Destroys the thread.
93
94
  int id() const;
95
    /// Returns the unique thread ID of the thread.
96
97
  TID tid() const;
98
    /// Returns the native thread ID of the thread.
99
100
  std::string name() const;
101
    /// Returns the name of the thread.
102
103
  std::string getName() const;
104
    /// Returns the name of the thread.
105
106
  void setName(const std::string& name);
107
    /// Sets the name of the thread.
108
    /// Note that it only take effect before start method invoked.
109
110
  void setPriority(Priority prio);
111
    /// Sets the thread's priority.
112
    ///
113
    /// Some platform only allow changing a thread's priority
114
    /// if the process has certain privileges.
115
116
  Priority getPriority() const;
117
    /// Returns the thread's priority.
118
119
  void setOSPriority(int prio, int policy = POLICY_DEFAULT);
120
    /// Sets the thread's priority, using an operating system specific
121
    /// priority value. Use getMinOSPriority() and getMaxOSPriority() to
122
    /// obtain mininum and maximum priority values. Additionally,
123
    /// a scheduling policy can be specified. The policy is currently
124
    /// only used on POSIX platforms where the values SCHED_OTHER (default),
125
    /// SCHED_FIFO and SCHED_RR are supported.
126
127
  int getOSPriority() const;
128
    /// Returns the thread's priority, expressed as an operating system
129
    /// specific priority value.
130
    ///
131
    /// May return 0 if the priority has not been explicitly set.
132
133
  static int getMinOSPriority(int policy = POLICY_DEFAULT);
134
    /// Returns the minimum operating system-specific priority value,
135
    /// which can be passed to setOSPriority() for the given policy.
136
137
  static int getMaxOSPriority(int policy = POLICY_DEFAULT);
138
    /// Returns the maximum operating system-specific priority value,
139
    /// which can be passed to setOSPriority() for the given policy.
140
141
  void setStackSize(int size);
142
    /// Sets the thread's stack size in bytes.
143
    /// Setting the stack size to 0 will use the default stack size.
144
    /// Typically, the real stack size is rounded up to the nearest
145
    /// page size multiple.
146
147
  int getStackSize() const;
148
    /// Returns the thread's stack size in bytes.
149
    /// If the default stack size is used, 0 is returned.
150
151
  void start(Runnable& target);
152
    /// Starts the thread with the given target.
153
    ///
154
    /// Note that the given Runnable object must remain
155
    /// valid during the entire lifetime of the thread, as
156
    /// only a reference to it is stored internally.
157
158
  void start(Poco::SharedPtr<Runnable> pTarget);
159
    /// Starts the thread with the given target.
160
    ///
161
    /// The Thread ensures that the given target stays
162
    /// alive while the thread is running.
163
164
  void start(Callable target, void* pData = nullptr);
165
    /// Starts the thread with the given target and parameter.
166
167
  template <class Functor>
168
  void startFunc(const Functor& fn)
169
    /// Starts the thread with the given functor object or lambda.
170
  {
171
    startImpl(new FunctorRunnable<Functor>(fn));
172
  }
173
174
  template <class Functor>
175
  void startFunc(Functor&& fn)
176
    /// Starts the thread with the given functor object or lambda.
177
  {
178
    startImpl(new FunctorRunnable<Functor>(std::move(fn)));
179
  }
180
181
  void join();
182
    /// Waits until the thread completes execution.
183
    /// If multiple threads try to join the same
184
    /// thread, the result is undefined.
185
186
  void join(long milliseconds);
187
    /// Waits for at most the given interval for the thread
188
    /// to complete. Throws a TimeoutException if the thread
189
    /// does not complete within the specified time interval.
190
191
  bool tryJoin(long milliseconds);
192
    /// Waits for at most the given interval for the thread
193
    /// to complete. Returns true if the thread has finished,
194
    /// false otherwise.
195
196
  bool isRunning() const;
197
    /// Returns true if the thread is running.
198
199
  static bool trySleep(long milliseconds);
200
    /// Starts an interruptible sleep. When trySleep() is called,
201
    /// the thread will remain suspended until:
202
    ///   - the timeout expires or
203
    ///   - wakeUp() is called
204
    ///
205
    /// Function returns true if sleep attempt was completed, false
206
    /// if sleep was interrupted by a wakeUp() call.
207
    /// A frequent scenario where trySleep()/wakeUp() pair of functions
208
    /// is useful is with threads spending most of the time idle,
209
    /// with periodic activity between the idle times; trying to sleep
210
    /// (as opposed to sleeping) allows immediate ending of idle thread
211
    /// from the outside.
212
    ///
213
    /// The trySleep() and wakeUp() calls should be used with
214
    /// understanding that the suspended state is not a true sleep,
215
    /// but rather a state of waiting for an event, with timeout
216
    /// expiration. This makes order of calls significant; calling
217
    /// wakeUp() before calling trySleep() will prevent the next
218
    /// trySleep() call to actually suspend the thread (which, in
219
    /// some scenarios, may be desirable behavior).
220
    ///
221
    /// Note that, unlike Thread::sleep(), this function can only
222
    /// be succesfully called from a thread started as Poco::Thread.
223
224
  void wakeUp();
225
    /// Wakes up the thread which is in the state of interruptible
226
    /// sleep. For threads that are not suspended, calling this
227
    /// function has the effect of preventing the subsequent
228
    /// trySleep() call to put thread in a suspended state.
229
230
  static void sleep(long milliseconds);
231
    /// Suspends the current thread for the specified
232
    /// amount of time.
233
234
  static void yield();
235
    /// Yields cpu to other threads.
236
237
  static Thread* current();
238
    /// Returns the Thread object for the currently active thread.
239
    /// If the current thread is the main thread, 0 is returned.
240
241
  static TID currentTid();
242
    /// Returns the native thread ID for the current thread.
243
244
  static long currentOsTid();
245
    /// Returns the operating system specific thread ID for the current thread.
246
    /// On error, or if the platform does not support this functionality, it returns zero.
247
248
  static void setCurrentName(const std::string& name);
249
    /// Sets the name of the current thread.
250
    /// Support for this feature varies across platforms.
251
    /// Any errors are silently ignored.
252
253
  static std::string getCurrentName();
254
    /// Returns the name of the current thread.
255
    /// Support for this feature varies across platforms.
256
    /// Returns an empty string if not supported, on error,
257
    /// or if no name has been set for the thread.
258
259
  bool setAffinity(int coreId);
260
    /// Sets the thread affinity to the coreID.
261
    /// Returns true if succesful.
262
    /// Returns false if not succesful or not
263
    /// implemented.
264
265
  int getAffinity() const;
266
    /// Returns the thread affinity.
267
    /// Negative value means the thread has
268
    /// no CPU core affinity.
269
270
  bool isInterrupted();
271
    /// Tests whether current thread has been interrupted.
272
    /// Return true if the task running on this thread should be stopped.
273
    /// An interruption can be requested by interrupt().
274
    ///
275
    /// This function can be used to make long running tasks cleanly interruptible.
276
    /// Never checking or acting on the value returned by this function is safe,
277
    /// however it is advisable do so regularly in long running functions.
278
    /// Take care not to call it too often, to keep the overhead low.
279
    /// 
280
    /// See also checkInterrupted().
281
282
  void checkInterrupted();
283
    /// Tests whether current thread has been interrupted.
284
    /// Throws Poco::ThreadInterruptedException if isInterrupted() return true.
285
    ///
286
    /// Note: The interrupted status of the thread is cleared by this method.
287
288
  void interrupt();
289
    /// Interrupts this thread.
290
    ///
291
    /// This function does not stop any event loop running on the thread and
292
    /// does not terminate it in any way.
293
    ///
294
    /// See also isInterrupted().
295
296
  void clearInterrupt();
297
    /// Clear the the interrupted status.
298
299
protected:
300
  ThreadLocalStorage& tls();
301
    /// Returns a reference to the thread's local storage.
302
303
  void clearTLS();
304
    /// Clears the thread's local storage.
305
306
  std::string makeName();
307
    /// Creates a unique name for a thread.
308
309
  static int uniqueId();
310
    /// Creates and returns a unique id for a thread.
311
312
  template <class Functor>
313
  class FunctorRunnable: public Runnable
314
  {
315
  public:
316
    FunctorRunnable(const Functor& functor):
317
      _functor(functor)
318
    {
319
    }
320
321
    FunctorRunnable(Functor&& functor):
322
      _functor(std::move(functor))
323
    {
324
    }
325
326
    ~FunctorRunnable() override = default;
327
328
    void run() override
329
    {
330
      _functor();
331
    }
332
333
  private:
334
    Functor _functor;
335
  };
336
337
private:
338
  Thread(const Thread&);
339
  Thread& operator = (const Thread&);
340
341
  int                 _id;
342
  ThreadLocalStorage* _pTLS;
343
  Event               _event;
344
  std::atomic_bool    _interruptionRequested;
345
346
  friend class ThreadLocalStorage;
347
  friend class PooledThread;
348
};
349
350
351
//
352
// inlines
353
//
354
inline Thread::TID Thread::tid() const
355
0
{
356
0
  return tidImpl();
357
0
}
358
359
360
inline int Thread::id() const
361
0
{
362
0
  return _id;
363
0
}
364
365
366
inline std::string Thread::name() const
367
0
{
368
0
  return getNameImpl();
369
0
}
370
371
372
inline std::string Thread::getName() const
373
0
{
374
0
  return getNameImpl();
375
0
}
376
377
378
inline bool Thread::isRunning() const
379
0
{
380
0
  return isRunningImpl();
381
0
}
382
383
384
inline void Thread::yield()
385
0
{
386
0
  yieldImpl();
387
0
}
388
389
390
inline void Thread::sleep(long milliseconds)
391
0
{
392
0
  std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
393
0
}
394
395
396
inline Thread* Thread::current()
397
0
{
398
0
  return static_cast<Thread*>(currentImpl());
399
0
}
400
401
402
inline void Thread::setOSPriority(int prio, int policy)
403
0
{
404
0
  setOSPriorityImpl(prio, policy);
405
0
}
406
407
408
inline int Thread::getOSPriority() const
409
0
{
410
0
  return getOSPriorityImpl();
411
0
}
412
413
414
inline int Thread::getMinOSPriority(int policy)
415
0
{
416
0
  return ThreadImpl::getMinOSPriorityImpl(policy);
417
0
}
418
419
420
inline int Thread::getMaxOSPriority(int policy)
421
0
{
422
0
  return ThreadImpl::getMaxOSPriorityImpl(policy);
423
0
}
424
425
426
inline void Thread::setStackSize(int size)
427
0
{
428
0
  setStackSizeImpl(size);
429
0
}
430
431
432
inline int Thread::getStackSize() const
433
0
{
434
0
  return getStackSizeImpl();
435
0
}
436
437
438
inline Thread::TID Thread::currentTid()
439
0
{
440
0
  return currentTidImpl();
441
0
}
442
443
inline long Thread::currentOsTid()
444
0
{
445
0
  return currentOsTidImpl();
446
0
}
447
448
inline void Thread::setCurrentName(const std::string& name)
449
0
{
450
0
#ifndef POCO_NO_THREADNAME
451
0
  setCurrentNameImpl(name);
452
0
#else
453
0
  (void)name;
454
0
#endif
455
0
}
456
457
inline std::string Thread::getCurrentName()
458
0
{
459
0
#ifndef POCO_NO_THREADNAME
460
0
  return getCurrentNameImpl();
461
0
#else
462
0
  return std::string();
463
0
#endif
464
0
}
465
466
inline bool Thread::setAffinity(int coreId)
467
0
{
468
0
  return setAffinityImpl(coreId);
469
0
}
470
471
472
inline int Thread::getAffinity() const
473
0
{
474
0
  return getAffinityImpl();
475
0
}
476
477
478
} // namespace Poco
479
480
481
#endif // Foundation_Thread_INCLUDED