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
217protected:
218 ThreadLocalStorage& tls();
219 /// Returns a reference to the thread's local storage.
220
221 void clearTLS();
222 /// Clears the thread's local storage.
223
224 std::string makeName();
225 /// Creates a unique name for a thread.
226
227 static int uniqueId();
228 /// Creates and returns a unique id for a thread.
229
230 template <class Functor>
231 class FunctorRunnable: public Runnable
232 {
233 public:
234 FunctorRunnable(const Functor& functor):
235 _functor(functor)
236 {
237 }
238
239 ~FunctorRunnable()
240 {
241 }
242
243 void run()
244 {
245 _functor();
246 }
247
248 private:
249 Functor _functor;
250 };
251
252private:
253 Thread(const Thread&);
254 Thread& operator = (const Thread&);
255
256 int _id;
257 std::string _name;
258 ThreadLocalStorage* _pTLS;
259 Event _event;
260 mutable FastMutex _mutex;
261
262 friend class ThreadLocalStorage;
263 friend class PooledThread;
264};
265
266
267//
268// inlines
269//
270inline Thread::TID Thread::tid() const
271{
272 return tidImpl();
273}
274
275
276inline int Thread::id() const
277{
278 return _id;
279}
280
281
282inline std::string Thread::name() const
283{
284 FastMutex::ScopedLock lock(_mutex);
285
286 return _name;
287}
288
289
290inline std::string Thread::getName() const
291{
292 FastMutex::ScopedLock lock(_mutex);
293
294 return _name;
295}
296
297
298inline bool Thread::isRunning() const
299{
300 return isRunningImpl();
301}
302
303
304inline void Thread::sleep(long milliseconds)
305{
306 sleepImpl(milliseconds);
307}
308
309
310inline void Thread::yield()
311{
312 yieldImpl();
313}
314
315
316inline Thread* Thread::current()
317{
318 return static_cast<Thread*>(currentImpl());
319}
320
321
322inline void Thread::setOSPriority(int prio, int policy)
323{
324 setOSPriorityImpl(prio, policy);
325}
326
327
328inline int Thread::getOSPriority() const
329{
330 return getOSPriorityImpl();
331}
332
333
334inline int Thread::getMinOSPriority(int policy)
335{
336 return ThreadImpl::getMinOSPriorityImpl(policy);
337}
338
339
340inline int Thread::getMaxOSPriority(int policy)
341{
342 return ThreadImpl::getMaxOSPriorityImpl(policy);
343}
344
345
346inline void Thread::setStackSize(int size)
347{
348 setStackSizeImpl(size);
349}
350
351
352inline void Thread::setAffinity(int cpu)
353{
354 setAffinityImpl(cpu);
355}
356
357
358inline int Thread::getAffinity() const
359{
360 return getAffinityImpl();
361}
362
363
364inline int Thread::getStackSize() const
365{
366 return getStackSizeImpl();
367}
368
369
370inline Thread::TID Thread::currentTid()
371{
372 return currentTidImpl();
373}
374
375
376} // namespace Poco
377
378
379#endif // Foundation_Thread_INCLUDED
380