diff --git a/src/servers/Server_Common/Util/LockedWaitQueue.h b/src/servers/Server_Common/Util/LockedWaitQueue.h new file mode 100644 index 00000000..22c1964f --- /dev/null +++ b/src/servers/Server_Common/Util/LockedWaitQueue.h @@ -0,0 +1,98 @@ +#ifndef _LOCKED_WAIT_H +#define _LOCKED_WAIT_H + +#include +#include +#include +#include +#include + +namespace Core +{ + +template< typename T > +class LockedWaitQueue +{ +private: + std::mutex m_queueLock; + std::queue< T > m_queue; + std::condition_variable m_condition; + std::atomic m_shutdown; + +public: + + LockedWaitQueue() : m_shutdown(false) { } + + void push( const T& value ) + { + std::lock_guard< std::mutex > lock( m_queueLock ); + m_queue.push( std::move( value ) ); + + m_condition.notify_one(); + } + + bool empty() + { + std::lock_guard< std::mutex > lock( m_queueLock ); + + return _queue.empty(); + } + + bool pop( T& value ) + { + std::lock_guard< std::mutex > lock( m_queueLock ); + + if( m_queue.empty() || m_shutdown ) + return false; + + value = m_queue.front(); + + m_queue.pop(); + + return true; + } + + void waitAndPop( T& value ) + { + std::unique_lock< std::mutex > lock( m_queueLock ); + + while( m_queue.empty() && !m_shutdown ) + m_condition.wait(lock); + + if( m_queue.empty() || m_shutdown ) + return; + + value = m_queue.front(); + + m_queue.pop(); + } + + void cancel() + { + std::unique_lock< std::mutex > lock( m_queueLock ); + + while( !m_queue.empty() ) + { + T& value = m_queue.front(); + + deleteQueuedObject( value ); + + m_queue.pop(); + } + + _shutdown = true; + + _condition.notify_all(); + } + +private: + template< typename E = T > + typename std::enable_if::value>::type deleteQueuedObject( E& obj ) { delete obj; } + + template< typename E = T > + typename std::enable_if::value>::type deleteQueuedObject( E const& ) { } +}; +} + +#endif +