]> git.mxchange.org Git - simgear.git/commitdiff
iAdded new classes to simgear/threads. SGGuard is a wrapper around a
authorcurt <curt>
Mon, 16 Apr 2001 17:26:13 +0000 (17:26 +0000)
committercurt <curt>
Mon, 16 Apr 2001 17:26:13 +0000 (17:26 +0000)
mutex that unlocks the mutex when the SGGuard object goes out of scope.
The SGxxxQueue<T> template family factor out the common behaviour we
need for passing data between threads.

configure.in
simgear/threads/Makefile.am
simgear/threads/SGGuard.hxx [new file with mode: 0644]
simgear/threads/SGQueue.hxx [new file with mode: 0644]

index bdaa48e4288dc350bf63f62cb41195d56e3956da..4f9553101e8d7c930dcbfaee1287588f5a8f0c3c 100644 (file)
@@ -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
index 53078d2809524554a008b2be939d7f94c3732a14..16e559bf55c10ed7a645ce3ab781c871dd177b7e 100644 (file)
@@ -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 (file)
index 0000000..7a890e7
--- /dev/null
@@ -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 LOCK>
+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 (file)
index 0000000..e5c2b28
--- /dev/null
@@ -0,0 +1,208 @@
+#ifndef SGQUEUE_HXX_INCLUDED
+#define SGQUEUE_HXX_INCLUDED 1
+
+#include <simgear/compiler.h>
+
+#if defined ( SG_HAVE_STD_INCLUDES )
+#  include <cassert>
+#else
+#  include <assert.h>
+#endif
+
+#include <queue>
+#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 T>
+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<T> fifo;
+};
+
+/**
+ * A simple thread safe queue.  All access functions are guarded with a mutex.
+ */
+template<class T, class LOCK=SGMutex>
+class SGLockedQueue : public SGQueue<T>
+{
+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<LOCK> 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<LOCK> g(mutex);
+       fifo.push( item );
+    }
+
+    /**
+     * Get an item from the head of the queue.
+     *
+     * @return T next available object.
+     */
+    virtual T pop() {
+       SGGuard<LOCK> 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 T>
+class SGBlockingQueue : public SGQueue<T>
+{
+public:
+    /**
+     * Create a new SGBlockingQueue.
+     */
+    SGBlockingQueue() {}
+
+    /**
+     * Destroy this queue.
+     */
+    ~SGBlockingQueue() { mutex.unlock(); }
+
+    /**
+     * 
+     */
+    virtual bool empty() {
+       SGGuard<SGMutex> 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<SGMutex> 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<SGMutex> 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