From 4f3aaa1ede95eb5a83bd92242b36cf80f0210150 Mon Sep 17 00:00:00 2001 From: curt Date: Mon, 16 Apr 2001 17:26:13 +0000 Subject: [PATCH] iAdded new classes to simgear/threads. SGGuard is a wrapper around a mutex that unlocks the mutex when the SGGuard object goes out of scope. The SGxxxQueue template family factor out the common behaviour we need for passing data between threads. --- configure.in | 4 +- simgear/threads/Makefile.am | 2 + simgear/threads/SGGuard.hxx | 38 +++++++ simgear/threads/SGQueue.hxx | 208 ++++++++++++++++++++++++++++++++++++ 4 files changed, 250 insertions(+), 2 deletions(-) create mode 100644 simgear/threads/SGGuard.hxx create mode 100644 simgear/threads/SGQueue.hxx diff --git a/configure.in b/configure.in index bdaa48e4..4f955310 100644 --- a/configure.in +++ b/configure.in @@ -345,7 +345,7 @@ if test "x$ac_cv_header_zlib_h" != "xyes"; then fi if test "x$ac_cv_lib_pthread_pthread_exit" = "xyes" -a "x$ac_cv_header_pthread_h" = "xyes"; then - echo "Threads: pthread is supported." + echo "Threads: pthread lib found." else - echo "Threads: no threads (pthreads not found.)" + echo "Threads: no threads (pthread lib not found.)" fi diff --git a/simgear/threads/Makefile.am b/simgear/threads/Makefile.am index 53078d28..16e559bf 100644 --- a/simgear/threads/Makefile.am +++ b/simgear/threads/Makefile.am @@ -3,6 +3,8 @@ includedir = @includedir@/threads lib_LIBRARIES = libsgthreads.a include_HEADERS = \ + SGGuard.hxx \ + SGQueue.hxx \ SGThread.hxx libsgthreads_a_SOURCES = \ diff --git a/simgear/threads/SGGuard.hxx b/simgear/threads/SGGuard.hxx new file mode 100644 index 00000000..7a890e72 --- /dev/null +++ b/simgear/threads/SGGuard.hxx @@ -0,0 +1,38 @@ +#ifndef SGGUARD_HXX_INCLUDED +#define SGGUARD_HXX_INCLUDED 1 + +/** + * A scoped locking utility. + * An SGGuard object locks its synchronization object during creation and + * automatically unlocks it when it goes out of scope. + */ +template +class SGGuard +{ +public: + + /** + * Create an SGGuard object and lock the passed lockable object. + * @param LOCK A lockable object. + */ + inline SGGuard( LOCK& l ) : lock(l) { lock.lock(); } + + /** + * Destroy this object and unlock the locakable object. + */ + inline ~SGGuard() { lock.unlock(); } + +private: + + /** + * A lockable object. + */ + LOCK& lock; + +private: + // Disable copying. + SGGuard(const LOCK&); + LOCK& operator= (const LOCK&); +}; + +#endif // SGGUARD_HXX_INCLUDED diff --git a/simgear/threads/SGQueue.hxx b/simgear/threads/SGQueue.hxx new file mode 100644 index 00000000..e5c2b280 --- /dev/null +++ b/simgear/threads/SGQueue.hxx @@ -0,0 +1,208 @@ +#ifndef SGQUEUE_HXX_INCLUDED +#define SGQUEUE_HXX_INCLUDED 1 + +#include + +#if defined ( SG_HAVE_STD_INCLUDES ) +# include +#else +# include +#endif + +#include +#include "SGThread.hxx" +#include "SGGuard.hxx" + +/** + * SGQueue defines an interface for a FIFO. + * It can be implemented using different types of synchronization + * and protection. + */ +template +class SGQueue +{ +public: + + /** + * Create a new SGQueue object. + */ + SGQueue() {} + + /** + * Destroy this object. + */ + virtual ~SGQueue() {} + + /** + * Returns whether this queue is empty (contains no elements). + * + * @return bool True if queue is empty, otherwisr false. + */ + virtual bool empty() = 0; + + /** + * Add an item to the end of the queue. + * + * @param T object to add. + */ + virtual void push( const T& item ) = 0; + + /** + * Get an item from the head of the queue. + * + * @return T next available object. + */ + virtual T pop() = 0; + +protected: + /** + * + */ + std::queue fifo; +}; + +/** + * A simple thread safe queue. All access functions are guarded with a mutex. + */ +template +class SGLockedQueue : public SGQueue +{ +public: + + /** + * Create a new SGLockedQueue object. + */ + SGLockedQueue() {} + + /** + * Destroy this object. + */ + ~SGLockedQueue() {} + + /** + * Returns whether this queue is empty (contains no elements). + * + * @return bool True if queue is empty, otherwisr false. + */ + virtual bool empty() { + SGGuard g(mutex); + return fifo.empty(); + } + + /** + * Add an item to the end of the queue. + * + * @param T object to add. + */ + virtual void push( const T& item ) { + SGGuard g(mutex); + fifo.push( item ); + } + + /** + * Get an item from the head of the queue. + * + * @return T next available object. + */ + virtual T pop() { + SGGuard g(mutex); + //if (fifo.empty()) throw NoSuchElementException(); + assert( ! fifo.empty() ); +// if (fifo.empty()) +// { +// mutex.unlock(); +// pthread_exit( PTHREAD_CANCELED ); +// } + T item = fifo.front(); + fifo.pop(); + return item; + } +private: + + /** + * Mutex to serialise access. + */ + LOCK mutex; + +private: + // Prevent copying. + SGLockedQueue(const SGLockedQueue&); + SGLockedQueue& operator= (const SGLockedQueue&); +}; + +/** + * A guarded queue blocks threads trying to retrieve items + * when none are available. + */ +template +class SGBlockingQueue : public SGQueue +{ +public: + /** + * Create a new SGBlockingQueue. + */ + SGBlockingQueue() {} + + /** + * Destroy this queue. + */ + ~SGBlockingQueue() { mutex.unlock(); } + + /** + * + */ + virtual bool empty() { + SGGuard g(mutex); + return fifo.empty(); + } + + /** + * Add an item to the end of the queue. + * + * @param T object to add. + */ + virtual void push( const T& item ) { + SGGuard g(mutex); + fifo.push( item ); + not_empty.signal(); + } + + /** + * Get an item from the head of the queue. + * If no items are available then the calling thread is suspended + * + * @return T next available object. + */ + virtual T pop() { + SGGuard g(mutex); + + while (fifo.empty()) + not_empty.wait(mutex); + + assert(fifo.empty() != true); + //if (fifo.empty()) throw ?? + + T item = fifo.front(); + fifo.pop(); + return item; + } + +private: + + /** + * Mutex to serialise access. + */ + SGMutex mutex; + + /** + * Condition to signal when queue not empty. + */ + SGCondition not_empty; + +private: + // Prevent copying. + SGBlockingQueue( const SGBlockingQueue& ); + SGBlockingQueue& operator=( const SGBlockingQueue& ); +}; + +#endif // SGQUEUE_HXX_INCLUDED -- 2.39.5