Files
simgear/simgear/threads/SGQueue.hxx
T
Mathias Froehlich 08003ceba9 Revert to simgears thread support.
For all source directories outside of simgear/scene,
which really depends very hard on osg, avoid using osg
classes. This should reenable the use of some basic and
scenegraph independent parts of simgear without the
the need for osg.
2011-09-07 17:32:43 +02:00

411 lines
7.7 KiB
C++

#ifndef SGQUEUE_HXX_INCLUDED
#define SGQUEUE_HXX_INCLUDED 1
#include <simgear/compiler.h>
#include <cassert>
#include <queue>
#include "SGGuard.hxx"
#include "SGThread.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;
/**
* View the item from the head of the queue.
*
* @return T next available object.
*/
virtual T front() = 0;
/**
* Get an item from the head of the queue.
*
* @return T 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;
};
/**
* A simple thread safe queue. All access functions are guarded with a mutex.
*/
template<class T>
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<SGMutex> g(mutex);
return this->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);
this->fifo.push( item );
}
/**
* View the item from the head of the queue.
*
* @return T 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.
*/
virtual T pop() {
SGGuard<SGMutex> g(mutex);
//if (fifo.empty()) throw NoSuchElementException();
assert( ! this->fifo.empty() );
// if (fifo.empty())
// {
// mutex.unlock();
// pthread_exit( PTHREAD_CANCELED );
// }
T item = this->fifo.front();
this->fifo.pop();
return item;
}
/**
* Query the size of the queue
*
* @return size_t size of queue.
*/
virtual size_t size() {
SGGuard<SGMutex> g(mutex);
return this->fifo.size();
}
private:
/**
* Mutex to serialise access.
*/
SGMutex 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() {}
/**
*
*/
virtual bool empty() {
SGGuard<SGMutex> g(mutex);
return this->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);
this->fifo.push( item );
not_empty.signal();
}
/**
* View the item from the head of the queue.
* Calling thread is not suspended
*
* @return T 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.
*/
virtual T pop() {
SGGuard<SGMutex> g(mutex);
while (this->fifo.empty())
not_empty.wait(mutex);
assert(this->fifo.empty() != true);
//if (fifo.empty()) throw ??
T item = this->fifo.front();
this->fifo.pop();
return item;
}
/**
* Query the size of the queue
*
* @return size_t size of queue.
*/
virtual size_t size() {
SGGuard<SGMutex> g(mutex);
return this->fifo.size();
}
private:
/**
* Mutex to serialise access.
*/
SGMutex mutex;
/**
* Condition to signal when queue not empty.
*/
SGWaitCondition not_empty;
private:
// Prevent copying.
SGBlockingQueue( const SGBlockingQueue& );
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.
*/
~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 T 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 T 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 T 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 T 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 T 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_t size of queue.
*/
virtual size_t size() {
SGGuard<SGMutex> g(mutex);
return this->queue.size();
}
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