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_ 393