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