OpenSceneGraph/include/OpenThreads/Thread
2012-03-21 17:36:20 +00:00

390 lines
12 KiB
C++

/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
//
// Thread - C++ Thread class
// ~~~~~~~~
//
#ifndef _OPENTHREADS_THREAD_
#define _OPENTHREADS_THREAD_
#include <sys/types.h>
#include <OpenThreads/Mutex>
namespace OpenThreads {
/**
* Get the number of processors.
*
* Note, systems where no support exists for querrying the number of processors, 1 is returned.
*
*/
extern OPENTHREAD_EXPORT_DIRECTIVE int GetNumberOfProcessors();
/**
* Set the processor affinity of current thread.
*
* Note, systems where no support exists no affinity will be set, and -1 will be returned.
*
*/
extern OPENTHREAD_EXPORT_DIRECTIVE int SetProcessorAffinityOfCurrentThread(unsigned int cpunum);
/**
* @class Thread
* @brief This class provides an object-oriented thread interface.
*/
class OPENTHREAD_EXPORT_DIRECTIVE Thread {
public:
/**
* Set the concurrency level for a running application. This method
* only has effect if the pthreads thread model is being used, and
* then only when that model is many-to-one (eg. irix).
* in other cases it is ignored. The concurrency level is only a
* *hint* as to the number of execution vehicles to use, the actual
* implementation may do anything it wants. Setting the value
* to 0 returns things to their default state.
*
* @return previous concurrency level, -1 indicates no-op.
*/
static int SetConcurrency(int concurrencyLevel);
/**
* Get the concurrency level for a running application. In this
* case, a return code of 0 means that the application is in default
* mode. A return code of -1 means that the application is incapable
* of setting an arbitrary concurrency, because it is a one-to-one
* execution model (sprocs, linuxThreads)
*/
static int GetConcurrency();
/**
* Enumerated Type for thread priority
*/
enum ThreadPriority {
THREAD_PRIORITY_MAX, /**< The maximum possible priority */
THREAD_PRIORITY_HIGH, /**< A high (but not max) setting */
THREAD_PRIORITY_NOMINAL, /**< An average priority */
THREAD_PRIORITY_LOW, /**< A low (but not min) setting */
THREAD_PRIORITY_MIN, /**< The miniumum possible priority */
THREAD_PRIORITY_DEFAULT /**< Priority scheduling default */
};
/**
* Enumerated Type for thread scheduling policy
*/
enum ThreadPolicy {
THREAD_SCHEDULE_FIFO, /**< First in, First out scheduling */
THREAD_SCHEDULE_ROUND_ROBIN, /**< Round-robin scheduling (LINUX_DEFAULT) */
THREAD_SCHEDULE_TIME_SHARE, /**< Time-share scheduling (IRIX DEFAULT) */
THREAD_SCHEDULE_DEFAULT /**< Default scheduling */
};
/**
* Constructor
*/
Thread();
/**
* Destructor
*/
virtual ~Thread();
/**
* Return a pointer to the current running thread
*/
static Thread *CurrentThread();
/**
* Initialize Threading in a program. This method must be called before
* you can do any threading in a program.
*/
static void Init();
/**
* Yield the processor.
*
* @note This method operates on the calling process. And is
* equivalent to calling sched_yield().
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
static int YieldCurrentThread();
/**
* This method will return the ThreadPriority of the master process.
* (ie, the one calling the thread->start() methods for the first time)
* The method will almost certainly return
* Thread::THREAD_PRIORITY_DEFAULT if
* Init() has not been called.
*
* @return the Thread::ThreadPriority of the master thread.
*/
static ThreadPriority GetMasterPriority() {return s_masterThreadPriority;};
/**
* Get a unique thread id. This id is monotonically increasing.
*
* @return a unique thread identifier
*/
int getThreadId();
/**
* Get the thread's process id. This is the pthread_t or pid_t value
* depending on the threading model being used.
*
* @return thread process id.
*/
size_t getProcessId();
/**
* Start the thread. This method will configure the thread, set
* it's priority, and spawn it.
*
* @note if the stack size specified setStackSize is smaller than the
* smallest allowable stack size, the threads stack size will be set to
* the minimum allowed, and may be retrieved via the getStackSize()
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
int start();
int startThread();
/**
* Test the cancel state of the thread. If the thread has been canceled
* this method will cause the thread to exit now. This method operates
* on the calling thread.
*
* Returns 0 if normal, -1 if called from a thread other that this.
*/
int testCancel();
/**
* Cancel the thread. Equivalent to SIGKILL.
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
virtual int cancel();
/**
* Set the thread's schedule priority. This is a complex method.
* Beware of thread priorities when using a many-to-many kernel
* entity implemenation (such as IRIX pthreads). If one is not carefull
* to manage the thread priorities, a priority inversion deadlock can
* easily occur (Although the OpenThreads::Mutex & OpenThreads::Barrier
* constructs have been designed with this senario in mind). Unless
* you have explicit need to set the schedule pirorites for a given
* task, it is best to leave them alone.
*
* @note some implementations (notably LinuxThreads and IRIX Sprocs)
* only alow you to decrease thread priorities dynamically. Thus,
* a lower priority thread will not allow it's priority to be raised
* on the fly.
*
* @note seting the environment variable OUTPUT_THREADLIB_SCHEDULING_INFO
* will output scheduling information for each thread to stdout.
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
int setSchedulePriority(ThreadPriority priority);
/**
* Get the thread's schedule priority (if able)
*
* @note seting the environment variable OUTPUT_THREADLIB_SCHEDULING_INFO
* will output scheduling information for each thread to stdout.
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
int getSchedulePriority();
/**
* Set the thread's scheduling policy (if able)
*
* @note On some implementations (notably IRIX Sprocs & LinuxThreads)
* The policy may prohibit the use of SCHEDULE_ROUND_ROBIN and
* SCHEDULE_FIFO policies - due to their real-time nature, and
* the danger of deadlocking the machine when used as super-user.
* In such cases, the command is a no-op.
*
* @note seting the environment variable OUTPUT_THREADLIB_SCHEDULING_INFO
* will output scheduling information for each thread to stdout.
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
int setSchedulePolicy(ThreadPolicy policy);
/**
* Get the thread's policy (if able)
*
* @note seting the environment variable OUTPUT_THREADLIB_SCHEDULING_INFO
* will output scheduling information for each thread to stdout.
*
* @return policy if normal, -1 if errno set, errno code otherwise.
*/
int getSchedulePolicy();
/**
* Set the thread's desired stack size (in bytes).
* This method is an attribute of the thread and must be called
* *before* the start() method is invoked.
*
* @note a return code of 13 (EACESS) means that the thread stack
* size can no longer be changed.
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
int setStackSize(size_t size);
/**
* Get the thread's desired stack size.
*
* @return the thread's stack size. 0 indicates that the stack size
* has either not yet been initialized, or not yet been specified by
* the application.
*/
size_t getStackSize();
/**
* Print the thread's scheduling information to stdout.
*/
void printSchedulingInfo();
/**
* Detach the thread from the calling process.
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
int detach();
/**
* Join the calling process with the thread
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
int join();
/**
* Disable thread cancelation altogether. Thread::cancel() has no effect.
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
int setCancelModeDisable();
/**
* Mark the thread to cancel aysncronously on Thread::cancel().
* (May not be available with process-level implementations).
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
int setCancelModeAsynchronous();
/**
* Mark the thread to cancel at the earliest convenience on
* Thread::cancel() (This is the default)
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
int setCancelModeDeferred();
/**
* Query the thread's running status
*
* @return true if running, false if not.
*/
bool isRunning();
/**
* Thread's run method. Must be implemented by derived classes.
* This is where the action happens.
*/
virtual void run() = 0;
/**
* Thread's cancel cleanup routine, called upon cancel(), after the
* cancelation has taken place, but before the thread exits completely.
* This method should be used to repair parts of the thread's data
* that may have been damaged by a pre-mature cancel. No-op by default.
*/
virtual void cancelCleanup() {};
void* getImplementation(){ return _prvData; };
/** Thread's processor affinity method. This binds a thread to a
* processor whenever possible. This call must be made before
* start() or startThread() and has no effect after the thread
* has been running. In the pthreads implementation, this is only
* implemented on sgi, through a pthread extension. On other pthread
* platforms this is ignored. Returns 0 on success, implementation's
* error on failure, or -1 if ignored.
*/
int setProcessorAffinity( unsigned int cpunum );
/** microSleep method, equivilant to the posix usleep(microsec).
* This is not strictly thread API but is used
* so often with threads. It's basically UNIX usleep. Parameter is
* number of microseconds we current thread to sleep. Returns 0 on
* succes, non-zero on failure (UNIX errno or GetLastError() will give
* detailed description.
*/
static int microSleep( unsigned int microsec);
private:
/**
* The Private Actions class is allowed to operate on private data.
*/
friend class ThreadPrivateActions;
/**
* Private copy constructor, to prevent tampering.
*/
Thread(const Thread &/*t*/) {};
/**
* Private copy assignment, to prevent tampering.
*/
Thread &operator=(const Thread &/*t*/) {return *(this);};
/**
* Implementation-specific data
*/
void * _prvData;
/**
* Master thread's priority, set by Thread::Init.
*/
static ThreadPriority s_masterThreadPriority;
/**
* Is initialized flag
*/
static bool s_isInitialized;
};
}
#endif // !_OPENTHREADS_THREAD_