openscenegraph
Thread
Go to the documentation of this file.
1/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version. The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14
15//
16// Thread - C++ Thread class
17// ~~~~~~~~
18//
19
20#ifndef _OPENTHREADS_THREAD_
21#define _OPENTHREADS_THREAD_
22
23#include <sys/types.h>
24
25#include <OpenThreads/Mutex>
26#include <OpenThreads/Affinity>
27
28namespace OpenThreads {
29
30/**
31 * Get the number of processors.
32 *
33 * Note, systems where no support exists for querying the number of processors, 1 is returned.
34 *
35 */
36extern OPENTHREAD_EXPORT_DIRECTIVE int GetNumberOfProcessors();
37
38/**
39 * Set the processor affinity of current thread.
40 */
41extern OPENTHREAD_EXPORT_DIRECTIVE int SetProcessorAffinityOfCurrentThread(const Affinity& affinity);
42
43
44/**
45 * @class Thread
46 * @brief This class provides an object-oriented thread interface.
47 */
48class OPENTHREAD_EXPORT_DIRECTIVE Thread {
49
50public:
51
52 /**
53 * Set the concurrency level for a running application. This method
54 * only has effect if the pthreads thread model is being used, and
55 * then only when that model is many-to-one (eg. irix).
56 * in other cases it is ignored. The concurrency level is only a
57 * *hint* as to the number of execution vehicles to use, the actual
58 * implementation may do anything it wants. Setting the value
59 * to 0 returns things to their default state.
60 *
61 * @return previous concurrency level, -1 indicates no-op.
62 */
63 static int SetConcurrency(int concurrencyLevel);
64
65 /**
66 * Get the concurrency level for a running application. In this
67 * case, a return code of 0 means that the application is in default
68 * mode. A return code of -1 means that the application is incapable
69 * of setting an arbitrary concurrency, because it is a one-to-one
70 * execution model (sprocs, linuxThreads)
71 */
72 static int GetConcurrency();
73
74 /**
75 * Enumerated Type for thread priority
76 */
77 enum ThreadPriority {
78
79 THREAD_PRIORITY_MAX, /**< The maximum possible priority */
80 THREAD_PRIORITY_HIGH, /**< A high (but not max) setting */
81 THREAD_PRIORITY_NOMINAL, /**< An average priority */
82 THREAD_PRIORITY_LOW, /**< A low (but not min) setting */
83 THREAD_PRIORITY_MIN, /**< The miniumum possible priority */
84 THREAD_PRIORITY_DEFAULT /**< Priority scheduling default */
85
86 };
87
88 /**
89 * Enumerated Type for thread scheduling policy
90 */
91 enum ThreadPolicy {
92
93 THREAD_SCHEDULE_FIFO, /**< First in, First out scheduling */
94 THREAD_SCHEDULE_ROUND_ROBIN, /**< Round-robin scheduling (LINUX_DEFAULT) */
95 THREAD_SCHEDULE_TIME_SHARE, /**< Time-share scheduling (IRIX DEFAULT) */
96 THREAD_SCHEDULE_DEFAULT /**< Default scheduling */
97
98 };
99
100 /**
101 * Constructor
102 */
103 Thread();
104
105 /**
106 * Destructor
107 */
108 virtual ~Thread();
109
110
111 /**
112 * Return a pointer to the current running thread, returns NULL for a non OpenThreads thread.
113 */
114 static Thread *CurrentThread();
115
116 /**
117 * Return the id of the current thread
118 */
119 static size_t CurrentThreadId();
120
121
122 /**
123 * Initialize Threading in a program. This method must be called before
124 * you can do any threading in a program.
125 */
126 static void Init();
127
128 /**
129 * Yield the processor.
130 *
131 * @note This method operates on the calling process. And is
132 * equivalent to calling sched_yield().
133 *
134 * @return 0 if normal, -1 if errno set, errno code otherwise.
135 */
136 static int YieldCurrentThread();
137
138 /**
139 * This method will return the ThreadPriority of the master process.
140 * (ie, the one calling the thread->start() methods for the first time)
141 * The method will almost certainly return
142 * Thread::THREAD_PRIORITY_DEFAULT if
143 * Init() has not been called.
144 *
145 * @return the Thread::ThreadPriority of the master thread.
146 */
147 static ThreadPriority GetMasterPriority() {return s_masterThreadPriority;};
148
149
150 /**
151 * Get a unique thread id. This id is monotonically increasing.
152 *
153 * @return a unique thread identifier
154 */
155 size_t getThreadId();
156
157 /**
158 * Get the thread's process id. This is the pthread_t or pid_t value
159 * depending on the threading model being used.
160 *
161 * @return thread process id.
162 */
163 size_t getProcessId();
164
165 /**
166 * Start the thread. This method will configure the thread, set
167 * it's priority, and spawn it.
168 *
169 * @note if the stack size specified setStackSize is smaller than the
170 * smallest allowable stack size, the threads stack size will be set to
171 * the minimum allowed, and may be retrieved via the getStackSize()
172 *
173 * @return 0 if normal, -1 if errno set, errno code otherwise.
174 */
175 int start();
176 int startThread();
177
178 /**
179 * Test the cancel state of the thread. If the thread has been canceled
180 * this method will cause the thread to exit now. This method operates
181 * on the calling thread.
182 *
183 * Returns 0 if normal, -1 if called from a thread other that this.
184 */
185 int testCancel();
186
187
188 /**
189 * Cancel the thread. Equivalent to SIGKILL.
190 *
191 * @return 0 if normal, -1 if errno set, errno code otherwise.
192 */
193 virtual int cancel();
194
195 /**
196 * Set the thread's schedule priority. This is a complex method.
197 * Beware of thread priorities when using a many-to-many kernel
198 * entity implementation (such as IRIX pthreads). If one is not careful
199 * to manage the thread priorities, a priority inversion deadlock can
200 * easily occur (Although the OpenThreads::Mutex & OpenThreads::Barrier
201 * constructs have been designed with this scenario in mind). Unless
202 * you have explicit need to set the schedule priorities for a given
203 * task, it is best to leave them alone.
204 *
205 * @note some implementations (notably LinuxThreads and IRIX Sprocs)
206 * only allow you to decrease thread priorities dynamically. Thus,
207 * a lower priority thread will not allow it's priority to be raised
208 * on the fly.
209 *
210 * @note setting the environment variable OUTPUT_THREADLIB_SCHEDULING_INFO
211 * will output scheduling information for each thread to stdout.
212 *
213 * @return 0 if normal, -1 if errno set, errno code otherwise.
214 */
215 int setSchedulePriority(ThreadPriority priority);
216
217 /**
218 * Get the thread's schedule priority (if able)
219 *
220 * @note setting the environment variable OUTPUT_THREADLIB_SCHEDULING_INFO
221 * will output scheduling information for each thread to stdout.
222 *
223 * @return 0 if normal, -1 if errno set, errno code otherwise.
224 */
225 int getSchedulePriority();
226
227 /**
228 * Set the thread's scheduling policy (if able)
229 *
230 * @note On some implementations (notably IRIX Sprocs & LinuxThreads)
231 * The policy may prohibit the use of SCHEDULE_ROUND_ROBIN and
232 * SCHEDULE_FIFO policies - due to their real-time nature, and
233 * the danger of deadlocking the machine when used as super-user.
234 * In such cases, the command is a no-op.
235 *
236 * @note setting the environment variable OUTPUT_THREADLIB_SCHEDULING_INFO
237 * will output scheduling information for each thread to stdout.
238 *
239 * @return 0 if normal, -1 if errno set, errno code otherwise.
240 */
241 int setSchedulePolicy(ThreadPolicy policy);
242
243 /**
244 * Get the thread's policy (if able)
245 *
246 * @note setting the environment variable OUTPUT_THREADLIB_SCHEDULING_INFO
247 * will output scheduling information for each thread to stdout.
248 *
249 * @return policy if normal, -1 if errno set, errno code otherwise.
250 */
251 int getSchedulePolicy();
252
253 /**
254 * Set the thread's desired stack size (in bytes).
255 * This method is an attribute of the thread and must be called
256 * *before* the start() method is invoked.
257 *
258 * @note a return code of 13 (EACESS) means that the thread stack
259 * size can no longer be changed.
260 *
261 * @return 0 if normal, -1 if errno set, errno code otherwise.
262 */
263 int setStackSize(size_t size);
264
265 /**
266 * Get the thread's desired stack size.
267 *
268 * @return the thread's stack size. 0 indicates that the stack size
269 * has either not yet been initialized, or not yet been specified by
270 * the application.
271 */
272 size_t getStackSize();
273
274 /**
275 * Print the thread's scheduling information to stdout.
276 */
277 void printSchedulingInfo();
278
279 /**
280 * Detach the thread from the calling process.
281 *
282 * @return 0 if normal, -1 if errno set, errno code otherwise.
283 */
284 int detach();
285
286 /**
287 * Join the calling process with the thread
288 *
289 * @return 0 if normal, -1 if errno set, errno code otherwise.
290 */
291 int join();
292
293 /**
294 * Disable thread cancellation altogether. Thread::cancel() has no effect.
295 *
296 * @return 0 if normal, -1 if errno set, errno code otherwise.
297 */
298 int setCancelModeDisable();
299
300 /**
301 * Mark the thread to cancel asynchronously on Thread::cancel().
302 * (May not be available with process-level implementations).
303 *
304 * @return 0 if normal, -1 if errno set, errno code otherwise.
305 */
306 int setCancelModeAsynchronous();
307
308 /**
309 * Mark the thread to cancel at the earliest convenience on
310 * Thread::cancel() (This is the default)
311 *
312 * @return 0 if normal, -1 if errno set, errno code otherwise.
313 */
314 int setCancelModeDeferred();
315
316 /**
317 * Query the thread's running status
318 *
319 * @return true if running, false if not.
320 */
321 bool isRunning();
322
323 /**
324 * Thread's run method. Must be implemented by derived classes.
325 * This is where the action happens.
326 */
327 virtual void run() = 0;
328
329 /**
330 * Thread's cancel cleanup routine, called upon cancel(), after the
331 * cancellation has taken place, but before the thread exits completely.
332 * This method should be used to repair parts of the thread's data
333 * that may have been damaged by a pre-mature cancel. No-op by default.
334 */
335 virtual void cancelCleanup() {};
336
337 void* getImplementation(){ return _prvData; };
338
339 /** Set the Thread's processor affinity to all, a single CPU or multiple CPU's
340 * This call must be made before
341 * start() or startThread() and has no effect after the thread
342 * has been running. Returns 0 on success, implementation's
343 * error on failure, or -1 if ignored.
344 */
345 int setProcessorAffinity( const Affinity& affinity);
346
347
348 /** microSleep method, equivalent to the posix usleep(microsec).
349 * This is not strictly thread API but is used
350 * so often with threads. It's basically UNIX usleep. Parameter is
351 * number of microseconds we current thread to sleep. Returns 0 on
352 * success, non-zero on failure (UNIX errno or GetLastError() will give
353 * detailed description.
354 */
355 static int microSleep( unsigned int microsec);
356
357private:
358
359 /**
360 * The Private Actions class is allowed to operate on private data.
361 */
362 friend class ThreadPrivateActions;
363
364 /**
365 * Private copy constructor, to prevent tampering.
366 */
367 Thread(const Thread &/*t*/) {};
368
369 /**
370 * Private copy assignment, to prevent tampering.
371 */
372 Thread &operator=(const Thread &/*t*/) {return *(this);};
373
374 /**
375 * Implementation-specific data
376 */
377 void * _prvData;
378
379 /**
380 * Master thread's priority, set by Thread::Init.
381 */
382 static ThreadPriority s_masterThreadPriority;
383
384 /**
385 * Is initialized flag
386 */
387 static bool s_isInitialized;
388};
389
390}
391
392#endif // !_OPENTHREADS_THREAD_