]> git.mxchange.org Git - simgear.git/blobdiff - simgear/threads/SGQueue.hxx
Introduce SGBinaryFile
[simgear.git] / simgear / threads / SGQueue.hxx
index 7a040be44e5118a0ba7bcb732178a8adada33e03..41c2cf306147eb512c0614907c2d86fb3c9c1ab3 100644 (file)
@@ -3,15 +3,10 @@
 
 #include <simgear/compiler.h>
 
-#if defined ( SG_HAVE_STD_INCLUDES )
-#  include <cassert>
-#else
-#  include <assert.h>
-#endif
-
+#include <cassert>
 #include <queue>
-#include "SGThread.hxx"
 #include "SGGuard.hxx"
+#include "SGThread.hxx"
 
 /**
  * SGQueue defines an interface for a FIFO.
@@ -43,20 +38,34 @@ public:
     /**
      * Add an item to the end of the queue.
      *
-     * @param T object to add.
+     * @param item  object to add.
      */
     virtual void push( const T& item ) = 0;
 
+    /**
+     * View the item from the head of the queue.
+     *
+     * @return The next available object.
+     */
+    virtual T front() = 0;
+
     /**
      * Get an item from the head of the queue.
      *
-     * @return T next available object.
+     * @return The next available object.
      */
     virtual T pop() = 0;
 
+    /**
+     * Query the size of the queue
+     *
+     * @return size_t size of queue.
+     */
+    virtual size_t size() = 0;
+
 protected:
     /**
-     * 
+     *
      */
     std::queue<T> fifo;
 };
@@ -64,7 +73,7 @@ protected:
 /**
  * A simple thread safe queue.  All access functions are guarded with a mutex.
  */
-template<class T, class SGLOCK=SGMutex>
+template<class T>
 class SGLockedQueue : public SGQueue<T>
 {
 public:
@@ -77,52 +86,75 @@ public:
     /**
      * Destroy this object.
      */
-    ~SGLockedQueue() {}
+    virtual ~SGLockedQueue() {}
 
     /**
      * Returns whether this queue is empty (contains no elements).
      *
-     * @return bool True if queue is empty, otherwisr false.
+     * @return True if queue is empty, otherwise false.
      */
     virtual bool empty() {
-       SGGuard<SGLOCK> g(mutex);
-       return fifo.empty();
+       SGGuard<SGMutex> g(mutex);
+       return this->fifo.empty();
     }
 
     /**
      * Add an item to the end of the queue.
      *
-     * @param T object to add.
+     * @param item object to add.
      */
     virtual void push( const T& item ) {
-       SGGuard<SGLOCK> g(mutex);
-       fifo.push( item );
+       SGGuard<SGMutex> g(mutex);
+       this->fifo.push( item );
+    }
+
+    /**
+     * View the item from the head of the queue.
+     *
+     * @return The next available object.
+     */
+    virtual T front() {
+       SGGuard<SGMutex> g(mutex);
+       assert( ! this->fifo.empty() );
+       T item = this->fifo.front();
+       return item;
     }
 
     /**
      * Get an item from the head of the queue.
      *
-     * @return T next available object.
+     * @return The next available object.
      */
     virtual T pop() {
-       SGGuard<SGLOCK> g(mutex);
-       //if (fifo.empty()) throw NoSuchElementException();
-       assert( ! fifo.empty() );
+       SGGuard<SGMutex> g(mutex);
+           if (this->fifo.empty()) return T(); // assumes T is default constructable
+        
 //     if (fifo.empty())
 //     {
 //         mutex.unlock();
 //         pthread_exit( PTHREAD_CANCELED );
 //     }
-       T item = fifo.front();
-       fifo.pop();
+       T item = this->fifo.front();
+       this->fifo.pop();
        return item;
     }
+
+    /**
+     * Query the size of the queue
+     *
+     * @return Size of queue.
+     */
+    virtual size_t size() {
+       SGGuard<SGMutex> g(mutex);
+        return this->fifo.size();
+    }
+
 private:
 
     /**
      * Mutex to serialise access.
      */
-    SGLOCK mutex;
+    SGMutex mutex;
 
 private:
     // Prevent copying.
@@ -146,47 +178,73 @@ public:
     /**
      * Destroy this queue.
      */
-    ~SGBlockingQueue() { mutex.unlock(); }
+    virtual ~SGBlockingQueue() {}
 
     /**
-     * 
+     *
      */
     virtual bool empty() {
        SGGuard<SGMutex> g(mutex);
-       return fifo.empty();
+       return this->fifo.empty();
     }
 
     /**
      * Add an item to the end of the queue.
      *
-     * @param T object to add.
+     * @param item The object to add.
      */
     virtual void push( const T& item ) {
        SGGuard<SGMutex> g(mutex);
-       fifo.push( item );
+       this->fifo.push( item );
        not_empty.signal();
     }
 
+    /**
+     * View the item from the head of the queue.
+     * Calling thread is not suspended
+     *
+     * @return The next available object.
+     */
+    virtual T front() {
+       SGGuard<SGMutex> g(mutex);
+
+       assert(this->fifo.empty() != true);
+       //if (fifo.empty()) throw ??
+
+       T item = this->fifo.front();
+       return item;
+    }
+
     /**
      * 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.
+     * @return The next available object.
      */
     virtual T pop() {
        SGGuard<SGMutex> g(mutex);
 
-       while (fifo.empty())
+       while (this->fifo.empty())
            not_empty.wait(mutex);
 
-       assert(fifo.empty() != true);
+       assert(this->fifo.empty() != true);
        //if (fifo.empty()) throw ??
 
-       T item = fifo.front();
-       fifo.pop();
+       T item = this->fifo.front();
+       this->fifo.pop();
        return item;
     }
 
+    /**
+     * Query the size of the queue
+     *
+     * @return Size of queue.
+     */
+    virtual size_t size() {
+       SGGuard<SGMutex> g(mutex);
+        return this->fifo.size();
+    }
+
 private:
 
     /**
@@ -197,7 +255,7 @@ private:
     /**
      * Condition to signal when queue not empty.
      */
-    SGCondition not_empty;
+    SGWaitCondition not_empty;
 
 private:
     // Prevent copying.
@@ -205,4 +263,153 @@ private:
     SGBlockingQueue& operator=( const SGBlockingQueue& );
 };
 
+
+/**
+ * A guarded deque blocks threads trying to retrieve items
+ * when none are available.
+ */
+template<class T>
+class SGBlockingDeque
+{
+public:
+    /**
+     * Create a new SGBlockingDequeue.
+     */
+    SGBlockingDeque() {}
+
+    /**
+     * Destroy this dequeue.
+     */
+    virtual ~SGBlockingDeque() {}
+
+    /**
+     *
+     */
+    virtual void clear() {
+    SGGuard<SGMutex> g(mutex);
+    this->queue.clear();
+    }
+
+    /**
+     *
+     */
+    virtual bool empty() {
+    SGGuard<SGMutex> g(mutex);
+    return this->queue.empty();
+    }
+
+    /**
+     * Add an item to the front of the queue.
+     *
+     * @param item The object to add.
+     */
+    virtual void push_front( const T& item ) {
+    SGGuard<SGMutex> g(mutex);
+    this->queue.push_front( item );
+    not_empty.signal();
+    }
+
+    /**
+     * Add an item to the back of the queue.
+     *
+     * @param item The object to add.
+     */
+    virtual void push_back( const T& item ) {
+    SGGuard<SGMutex> g(mutex);
+    this->queue.push_back( item );
+    not_empty.signal();
+    }
+
+    /**
+     * View the item from the head of the queue.
+     * Calling thread is not suspended
+     *
+     * @return The next available object.
+     */
+    virtual T front() {
+    SGGuard<SGMutex> g(mutex);
+
+    assert(this->queue.empty() != true);
+    //if (queue.empty()) throw ??
+
+    T item = this->queue.front();
+    return item;
+    }
+
+    /**
+     * Get an item from the head of the queue.
+     * If no items are available then the calling thread is suspended
+     *
+     * @return The next available object.
+     */
+    virtual T pop_front() {
+    SGGuard<SGMutex> g(mutex);
+
+    while (this->queue.empty())
+        not_empty.wait(mutex);
+
+    assert(this->queue.empty() != true);
+    //if (queue.empty()) throw ??
+
+    T item = this->queue.front();
+    this->queue.pop_front();
+    return item;
+    }
+
+    /**
+     * Get an item from the tail of the queue.
+     * If no items are available then the calling thread is suspended
+     *
+     * @return The next available object.
+     */
+    virtual T pop_back() {
+    SGGuard<SGMutex> g(mutex);
+
+    while (this->queue.empty())
+        not_empty.wait(mutex);
+
+    assert(this->queue.empty() != true);
+    //if (queue.empty()) throw ??
+
+    T item = this->queue.back();
+    this->queue.pop_back();
+    return item;
+    }
+
+    /**
+     * Query the size of the queue
+     *
+     * @return Size of queue.
+     */
+    virtual size_t size() {
+    SGGuard<SGMutex> g(mutex);
+        return this->queue.size();
+    }
+
+    void waitOnNotEmpty() {
+       SGGuard<SGMutex> g(mutex);
+       while (this->queue.empty())
+           not_empty.wait(mutex);
+    }
+private:
+
+    /**
+     * Mutex to serialise access.
+     */
+    SGMutex mutex;
+
+    /**
+     * Condition to signal when queue not empty.
+     */
+    SGWaitCondition not_empty;
+
+private:
+    // Prevent copying.
+    SGBlockingDeque( const SGBlockingDeque& );
+    SGBlockingDeque& operator=( const SGBlockingDeque& );
+
+protected:
+    std::deque<T> queue;
+};
+
 #endif // SGQUEUE_HXX_INCLUDED