Coverage Report

Created: 2025-08-28 07:02

/src/poco/Foundation/include/Poco/Thread.h
Line
Count
Source (jump to first uncovered line)
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
  bool setAffinity(int coreId);
249
    /// Sets the thread affinity to the coreID.
250
    /// Returns true if succesful.
251
    /// Returns false if not succesful or not
252
    /// implemented.
253
254
  int getAffinity() const;
255
    /// Returns the thread affinity.
256
    /// Negative value means the thread has
257
    /// no CPU core affinity.
258
259
protected:
260
  ThreadLocalStorage& tls();
261
    /// Returns a reference to the thread's local storage.
262
263
  void clearTLS();
264
    /// Clears the thread's local storage.
265
266
  std::string makeName();
267
    /// Creates a unique name for a thread.
268
269
  static int uniqueId();
270
    /// Creates and returns a unique id for a thread.
271
272
  template <class Functor>
273
  class FunctorRunnable: public Runnable
274
  {
275
  public:
276
    FunctorRunnable(const Functor& functor):
277
      _functor(functor)
278
    {
279
    }
280
281
    FunctorRunnable(Functor&& functor):
282
      _functor(std::move(functor))
283
    {
284
    }
285
286
    ~FunctorRunnable() override = default;
287
288
    void run() override
289
    {
290
      _functor();
291
    }
292
293
  private:
294
    Functor _functor;
295
  };
296
297
private:
298
  Thread(const Thread&);
299
  Thread& operator = (const Thread&);
300
301
  int                 _id;
302
  ThreadLocalStorage* _pTLS;
303
  Event               _event;
304
305
  friend class ThreadLocalStorage;
306
  friend class PooledThread;
307
};
308
309
310
//
311
// inlines
312
//
313
inline Thread::TID Thread::tid() const
314
0
{
315
0
  return tidImpl();
316
0
}
317
318
319
inline int Thread::id() const
320
0
{
321
0
  return _id;
322
0
}
323
324
325
inline std::string Thread::name() const
326
0
{
327
0
  return getNameImpl();
328
0
}
329
330
331
inline std::string Thread::getName() const
332
0
{
333
0
  return getNameImpl();
334
0
}
335
336
337
inline bool Thread::isRunning() const
338
0
{
339
0
  return isRunningImpl();
340
0
}
341
342
343
inline void Thread::yield()
344
0
{
345
0
  yieldImpl();
346
0
}
347
348
349
inline void Thread::sleep(long milliseconds)
350
0
{
351
0
  std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
352
0
}
353
354
355
inline Thread* Thread::current()
356
0
{
357
0
  return static_cast<Thread*>(currentImpl());
358
0
}
359
360
361
inline void Thread::setOSPriority(int prio, int policy)
362
0
{
363
0
  setOSPriorityImpl(prio, policy);
364
0
}
365
366
367
inline int Thread::getOSPriority() const
368
0
{
369
0
  return getOSPriorityImpl();
370
0
}
371
372
373
inline int Thread::getMinOSPriority(int policy)
374
0
{
375
0
  return ThreadImpl::getMinOSPriorityImpl(policy);
376
0
}
377
378
379
inline int Thread::getMaxOSPriority(int policy)
380
0
{
381
0
  return ThreadImpl::getMaxOSPriorityImpl(policy);
382
0
}
383
384
385
inline void Thread::setStackSize(int size)
386
0
{
387
0
  setStackSizeImpl(size);
388
0
}
389
390
391
inline int Thread::getStackSize() const
392
0
{
393
0
  return getStackSizeImpl();
394
0
}
395
396
397
inline Thread::TID Thread::currentTid()
398
0
{
399
0
  return currentTidImpl();
400
0
}
401
402
inline long Thread::currentOsTid()
403
0
{
404
0
  return currentOsTidImpl();
405
0
}
406
407
inline bool Thread::setAffinity(int coreId)
408
0
{
409
0
  return setAffinityImpl(coreId);
410
0
}
411
412
413
inline int Thread::getAffinity() const
414
0
{
415
0
  return getAffinityImpl();
416
0
}
417
418
419
} // namespace Poco
420
421
422
#endif // Foundation_Thread_INCLUDED