X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fthreads%2FSGThread.hxx;h=477ca458f354b6f10807e766a00aa3f006386b1d;hb=b47d1ad5fd8ed111cae99c1f65f5bb65a5371501;hp=9440a356ce5054f3a450cfc8b6f603704791710d;hpb=0b316a8c5ee9c36f183c2ad0ef6686e2ed5f47c1;p=simgear.git diff --git a/simgear/threads/SGThread.hxx b/simgear/threads/SGThread.hxx index 9440a356..477ca458 100644 --- a/simgear/threads/SGThread.hxx +++ b/simgear/threads/SGThread.hxx @@ -16,13 +16,15 @@ // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // $Id$ #ifndef SGTHREAD_HXX_INCLUDED #define SGTHREAD_HXX_INCLUDED 1 +#include + #include #include #include @@ -40,43 +42,69 @@ extern "C" { class SGThread { public: - /** - * + * SGThread cancelation modes. */ - SGThread(); + enum cancel_t + { + CANCEL_DISABLE = 0, + CANCEL_DEFERRED, + CANCEL_IMMEDIATE + }; +public: /** - * + * Create a new thread object. + * When a SGThread object is created it does not begin execution + * immediately. It is started by calling the start() member function. */ - virtual ~SGThread(); + SGThread(); /** - * + * Start the underlying thread of execution. + * @param cpu An optional parameter to specify on which CPU to run this + * thread (only supported on IRIX at this time). + * @return Pthread error code if execution fails, otherwise returns 0. */ - int start(); + int start( unsigned cpu = 0 ); /** - * + * Sends a cancellation request to the underlying thread. The target + * thread will either ignore the request, honor it immediately or defer + * it until it reaches a cancellation point. */ void cancel(); /** - * + * Suspends the exection of the calling thread until this thread + * terminates. */ void join(); protected: + /** + * Destroy a thread object. + * This is protected so that its illegal to simply delete a thread + * - it must return from its run() function. + */ + virtual ~SGThread(); /** - * + * Set the threads cancellation mode. + * @param mode The required cancellation mode. + */ + void set_cancel( cancel_t mode ); + + /** + * All threads execute by deriving the run() method of SGThread. + * If this function terminates then the thread also terminates. */ virtual void run() = 0; private: /** - * + * Pthread thread identifier. */ pthread_t tid; @@ -99,10 +127,15 @@ SGThread::~SGThread() } inline int -SGThread::start() +SGThread::start( unsigned cpu ) { int status = pthread_create( &tid, 0, start_handler, this ); assert( status == 0 ); + (void)status; +#if defined( sgi ) + if ( !status && !cpu ) + pthread_setrunon_np( cpu ); +#endif return status; } @@ -111,6 +144,7 @@ SGThread::join() { int status = pthread_join( tid, 0 ); assert( status == 0 ); + (void)status; } inline void @@ -118,6 +152,7 @@ SGThread::cancel() { int status = pthread_cancel( tid ); assert( status == 0 ); + (void)status; } /** @@ -126,36 +161,55 @@ SGThread::cancel() */ class SGMutex { - friend class SGCondition; + friend class SGPthreadCond; public: /** * Create a new mutex. + * Under Linux this is a 'fast' mutex. */ SGMutex(); /** * Destroy a mutex object. + * Note: it is the responsibility of the caller to ensure the mutex is + * unlocked before destruction occurs. */ ~SGMutex(); /** - * + * Lock this mutex. + * If the mutex is currently unlocked, it becomes locked and owned by + * the calling thread. If the mutex is already locked by another thread, + * the calling thread is suspended until the mutex is unlocked. If the + * mutex is already locked and owned by the calling thread, the calling + * thread is suspended until the mutex is unlocked, effectively causing + * the calling thread to deadlock. + * + * @see SGMutex::trylock */ void lock(); /** - * + * Try to lock the mutex for the current thread. Behaves like lock except + * that it doesn't block the calling thread. + * @return true if mutex was successfully locked, otherwise false. + * @see SGMutex::lock */ bool trylock(); /** - * + * Unlock this mutex. + * It is assumed that the mutex is locked and owned by the calling thread. */ void unlock(); protected: + + /** + * Pthread mutex. + */ pthread_mutex_t mutex; }; @@ -163,41 +217,48 @@ inline SGMutex::SGMutex() { int status = pthread_mutex_init( &mutex, 0 ); assert( status == 0 ); + (void)status; } inline SGMutex::~SGMutex() { int status = pthread_mutex_destroy( &mutex ); assert( status == 0 ); + (void)status; } inline void SGMutex::lock() { int status = pthread_mutex_lock( &mutex ); assert( status == 0 ); + (void)status; } inline void SGMutex::unlock() { int status = pthread_mutex_unlock( &mutex ); assert( status == 0 ); + (void)status; } /** - * + * A condition variable is a synchronization device that allows threads to + * suspend execution until some predicate on shared data is satisfied. + * A condition variable is always associated with a mutex to avoid race + * conditions. */ -class SGCondition +class SGPthreadCond { public: /** * Create a new condition variable. */ - SGCondition(); + SGPthreadCond(); /** * Destroy the condition object. */ - ~SGCondition(); + ~SGPthreadCond(); /** * Wait for this condition variable to be signaled. @@ -210,8 +271,8 @@ public: * Wait for this condition variable to be signaled for at most * 'ms' milliseconds. * - * @param SGMutex& reference to a locked mutex. - * @param unsigned long milliseconds to wait for a signal. + * @param mutex reference to a locked mutex. + * @param ms milliseconds to wait for a signal. * * @return */ @@ -219,52 +280,64 @@ public: /** * Wake one thread waiting on this condition variable. + * Nothing happens if no threads are waiting. + * If several threads are waiting exactly one thread is restarted. It + * is not specified which. */ void signal(); /** * Wake all threads waiting on this condition variable. + * Nothing happens if no threads are waiting. */ void broadcast(); private: // Disable copying. - SGCondition(const SGCondition& ); - SGCondition& operator=(const SGCondition& ); + SGPthreadCond(const SGPthreadCond& ); + SGPthreadCond& operator=(const SGPthreadCond& ); private: + /** + * The Pthread conditon variable. + */ pthread_cond_t cond; }; -inline SGCondition::SGCondition() +inline SGPthreadCond::SGPthreadCond() { int status = pthread_cond_init( &cond, 0 ); assert( status == 0 ); + (void)status; } -inline SGCondition::~SGCondition() +inline SGPthreadCond::~SGPthreadCond() { int status = pthread_cond_destroy( &cond ); assert( status == 0 ); + (void)status; } -inline void SGCondition::signal() +inline void SGPthreadCond::signal() { int status = pthread_cond_signal( &cond ); assert( status == 0 ); + (void)status; } -inline void SGCondition::broadcast() +inline void SGPthreadCond::broadcast() { int status = pthread_cond_broadcast( &cond ); assert( status == 0 ); + (void)status; } -inline void SGCondition::wait( SGMutex& mutex ) +inline void SGPthreadCond::wait( SGMutex& mutex ) { int status = pthread_cond_wait( &cond, &mutex.mutex ); assert( status == 0 ); + (void)status; } #endif /* SGTHREAD_HXX_INCLUDED */