//
// 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 <simgear/compiler.h>
+
#include <pthread.h>
-#include <cassert>
-#include <cerrno>
+#if defined ( SG_HAVE_STD_INCLUDES )
+# include <cassert>
+# include <cerrno>
+#else
+# include <assert.h>
+# include <sys/errno.h>
+#endif
class SGThread;
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;
}
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;
}
{
int status = pthread_join( tid, 0 );
assert( status == 0 );
+ (void)status;
}
inline void
{
int status = pthread_cancel( tid );
assert( status == 0 );
+ (void)status;
}
/**
*/
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;
};
{
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.
* 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
*/
/**
* 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 */