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 "Poco/Environment.h"
25#include "Poco/Thread_STD.h"
26
27
28namespace Poco {
29
30
31class Runnable;
32class ThreadLocalStorage;
33
34
35class Foundation_API Thread: private ThreadImpl
36 /// This class implements a platform-independent
37 /// wrapper to an operating system thread.
38 ///
39 /// Every Thread object gets a unique (within
40 /// its process) numeric thread ID.
41 /// Furthermore, a thread can be assigned a name.
42 /// The name of a thread can be changed at any time.
43{
44public:
45 typedef ThreadImpl::TIDImpl TID;
46
47 using ThreadImpl::Callable;
48
49 enum Priority
50 /// Thread priorities.
51 {
52 PRIO_LOWEST = PRIO_LOWEST_IMPL, /// The lowest thread priority.
53 PRIO_LOW = PRIO_LOW_IMPL, /// A lower than normal thread priority.
54 PRIO_NORMAL = PRIO_NORMAL_IMPL, /// The normal thread priority.
55 PRIO_HIGH = PRIO_HIGH_IMPL, /// A higher than normal thread priority.
56 PRIO_HIGHEST = PRIO_HIGHEST_IMPL /// The highest thread priority.
57 };
58
59 enum Policy
60 {
61 POLICY_DEFAULT = POLICY_DEFAULT_IMPL
62 };
63
64 Thread();
65 /// Creates a thread. Call start() to start it.
66
67 Thread(const std::string& name);
68 /// Creates a named thread. Call start() to start it.
69
70 ~Thread();
71 /// Destroys the thread.
72
73 int id() const;
74 /// Returns the unique thread ID of the thread.
75
76 TID tid() const;
77 /// Returns the native thread ID of the thread.
78
79 std::string name() const;
80 /// Returns the name of the thread.
81
82 std::string getName() const;
83 /// Returns the name of the thread.
84
85 void setName(const std::string& name);
86 /// Sets the name of the thread.
87
88 void setPriority(Priority prio);
89 /// Sets the thread's priority.
90 ///
91 /// Some platform only allow changing a thread's priority
92 /// if the process has certain privileges.
93
94 Priority getPriority() const;
95 /// Returns the thread's priority.
96
97 void setOSPriority(int prio, int policy = POLICY_DEFAULT);
98 /// Sets the thread's priority, using an operating system specific
99 /// priority value. Use getMinOSPriority() and getMaxOSPriority() to
100 /// obtain minimum and maximum priority values. Additionally,
101 /// a scheduling policy can be specified. The policy is currently
102 /// only used on POSIX platforms where the values SCHED_OTHER (default),
103 /// SCHED_FIFO and SCHED_RR are supported.
104
105 int getOSPriority() const;
106 /// Returns the thread's priority, expressed as an operating system
107 /// specific priority value.
108 ///
109 /// May return 0 if the priority has not been explicitly set.
110
111 static int getMinOSPriority(int policy = POLICY_DEFAULT);
112 /// Returns the minimum operating system-specific priority value,
113 /// which can be passed to setOSPriority() for the given policy.
114
115 static int getMaxOSPriority(int policy = POLICY_DEFAULT);
116 /// Returns the maximum operating system-specific priority value,
117 /// which can be passed to setOSPriority() for the given policy.
118
119 void setStackSize(int size);
120 /// Sets the thread's stack size in bytes.
121 /// Setting the stack size to 0 will use the default stack size.
122 /// Typically, the real stack size is rounded up to the nearest
123 /// page size multiple.
124
125 void setAffinity(int cpu);
126 /// Binds the thread to run only on the CPU core with the
127 /// given index.
128 ///
129 /// Does nothing if the system does not support CPU affinity for
130 /// threads.
131
132 int getAffinity() const;
133 /// Returns the index of the CPU core this thread has been bound to,
134 /// or -1 if the thread has not been bound to a CPU.
135
136 int getStackSize() const;
137 /// Returns the thread's stack size in bytes.
138 /// If the default stack size is used, 0 is returned.
139
140 void start(Runnable& target);
141 /// Starts the thread with the given target.
142 ///
143 /// Note that the given Runnable object must remain
144 /// valid during the entire lifetime of the thread, as
145 /// only a reference to it is stored internally.
146
147 void start(Callable target, void* pData = 0);
148 /// Starts the thread with the given target and parameter.
149
150 template <class Functor>
151 void startFunc(Functor fn)
152 /// Starts the thread with the given functor object or lambda.
153 {
154 startImpl(new FunctorRunnable<Functor>(fn));
155 }
156
157 void join();
158 /// Waits until the thread completes execution.
159 /// If multiple threads try to join the same
160 /// thread, the result is undefined.
161
162 void join(long milliseconds);
163 /// Waits for at most the given interval for the thread
164 /// to complete. Throws a TimeoutException if the thread
165 /// does not complete within the specified time interval.
166
167 bool tryJoin(long milliseconds);
168 /// Waits for at most the given interval for the thread
169 /// to complete. Returns true if the thread has finished,
170 /// false otherwise.
171
172 bool isRunning() const;
173 /// Returns true if the thread is running.
174
175 static bool trySleep(long milliseconds);
176 /// Starts an interruptible sleep. When trySleep() is called,
177 /// the thread will remain suspended until:
178 /// - the timeout expires or
179 /// - wakeUp() is called
180 ///
181 /// Function returns true if sleep attempt was completed, false
182 /// if sleep was interrupted by a wakeUp() call.
183 /// A frequent scenario where trySleep()/wakeUp() pair of functions
184 /// is useful is with threads spending most of the time idle,
185 /// with periodic activity between the idle times; trying to sleep
186 /// (as opposed to sleeping) allows immediate ending of idle thread
187 /// from the outside.
188 ///
189 /// The trySleep() and wakeUp() calls should be used with
190 /// understanding that the suspended state is not a true sleep,
191 /// but rather a state of waiting for an event, with timeout
192 /// expiration. This makes order of calls significant; calling
193 /// wakeUp() before calling trySleep() will prevent the next
194 /// trySleep() call to actually suspend the thread (which, in
195 /// some scenarios, may be desirable behavior).
196
197 void wakeUp();
198 /// Wakes up the thread which is in the state of interruptible
199 /// sleep. For threads that are not suspended, calling this
200 /// function has the effect of preventing the subsequent
201 /// trySleep() call to put thread in a suspended state.
202
203 static void sleep(long milliseconds);
204 /// Suspends the current thread for the specified
205 /// amount of time.
206
207 static void yield();
208 /// Yields cpu to other threads.
209
210 static Thread* current();
211 /// Returns the Thread object for the currently active thread.
212 /// If the current thread is the main thread, 0 is returned.
213
214 static TID currentTid();
215 /// Returns the native thread ID for the current thread.
216
217 static long currentOsTid();
218 /// Returns the operating system specific thread ID for the current thread.
219
220protected:
221 ThreadLocalStorage& tls();
222 /// Returns a reference to the thread's local storage.
223
224 void clearTLS();
225 /// Clears the thread's local storage.
226
227 std::string makeName();
228 /// Creates a unique name for a thread.
229
230 static int uniqueId();
231 /// Creates and returns a unique id for a thread.
232
233 template <class Functor>
234 class FunctorRunnable: public Runnable
235 {
236 public:
237 FunctorRunnable(const Functor& functor):
238 _functor(functor)
239 {
240 }
241
242 ~FunctorRunnable()
243 {
244 }
245
246 void run()
247 {
248 _functor();
249 }
250
251 private:
252 Functor _functor;
253 };
254
255private:
256 Thread(const Thread&);
257 Thread& operator = (const Thread&);
258
259 int _id;
260 std::string _name;
261 ThreadLocalStorage* _pTLS;
262 Event _event;
263 mutable FastMutex _mutex;
264
265 friend class ThreadLocalStorage;
266 friend class PooledThread;
267};
268
269
270//
271// inlines
272//
273inline Thread::TID Thread::tid() const
274{
275 return tidImpl();
276}
277
278
279inline int Thread::id() const
280{
281 return _id;
282}
283
284
285inline std::string Thread::name() const
286{
287 FastMutex::ScopedLock lock(_mutex);
288
289 return _name;
290}
291
292
293inline std::string Thread::getName() const
294{
295 FastMutex::ScopedLock lock(_mutex);
296
297 return _name;
298}
299
300
301inline bool Thread::isRunning() const
302{
303 return isRunningImpl();
304}
305
306
307inline void Thread::sleep(long milliseconds)
308{
309 sleepImpl(milliseconds);
310}
311
312
313inline void Thread::yield()
314{
315 yieldImpl();
316}
317
318
319inline Thread* Thread::current()
320{
321 return static_cast<Thread*>(currentImpl());
322}
323
324
325inline void Thread::setOSPriority(int prio, int policy)
326{
327 setOSPriorityImpl(prio, policy);
328}
329
330
331inline int Thread::getOSPriority() const
332{
333 return getOSPriorityImpl();
334}
335
336
337inline int Thread::getMinOSPriority(int policy)
338{
339 return ThreadImpl::getMinOSPriorityImpl(policy);
340}
341
342
343inline int Thread::getMaxOSPriority(int policy)
344{
345 return ThreadImpl::getMaxOSPriorityImpl(policy);
346}
347
348
349inline void Thread::setStackSize(int size)
350{
351 setStackSizeImpl(size);
352}
353
354
355inline void Thread::setAffinity(int cpu)
356{
357 setAffinityImpl(cpu);
358}
359
360
361inline int Thread::getAffinity() const
362{
363 return getAffinityImpl();
364}
365
366
367inline int Thread::getStackSize() const
368{
369 return getStackSizeImpl();
370}
371
372
373inline Thread::TID Thread::currentTid()
374{
375 return currentTidImpl();
376}
377
378
379inline long Thread::currentOsTid()
380{
381 return currentOsTidImpl();
382}
383
384
385} // namespace Poco
386
387
388#endif // Foundation_Thread_INCLUDED
389