1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-27 14:57:44 +00:00
sapphire/src/common/Util/LockedWaitQueue.h

108 lines
1.9 KiB
C
Raw Normal View History

2017-09-25 14:43:32 +02:00
#ifndef _LOCKED_WAIT_H
#define _LOCKED_WAIT_H
#include <condition_variable>
#include <mutex>
#include <queue>
#include <atomic>
#include <type_traits>
#include <utility>
2017-09-25 14:43:32 +02:00
namespace Sapphire
2017-09-25 14:43:32 +02:00
{
2018-10-28 21:53:21 +01:00
template< typename T >
class LockedWaitQueue
{
2018-10-28 21:53:21 +01:00
private:
std::mutex m_queueLock;
std::queue< T > m_queue;
std::condition_variable m_condition;
std::atomic< bool > m_shutdown;
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
public:
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
LockedWaitQueue< T >() :
m_shutdown( false )
{
}
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
void push( const T& value )
{
std::lock_guard< std::mutex > lock( m_queueLock );
m_queue.push( std::move( value ) );
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
m_condition.notify_one();
}
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
bool empty()
{
std::lock_guard< std::mutex > lock( m_queueLock );
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
return m_queue.empty();
}
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
bool pop( T& value )
{
std::lock_guard< std::mutex > lock( m_queueLock );
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
if( m_queue.empty() || m_shutdown )
return false;
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
value = m_queue.front();
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
m_queue.pop();
return true;
}
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
void waitAndPop( T& value )
{
std::unique_lock< std::mutex > lock( m_queueLock );
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
while( m_queue.empty() && !m_shutdown )
m_condition.wait( lock );
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
if( m_queue.empty() || m_shutdown )
return;
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
value = m_queue.front();
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
m_queue.pop();
}
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
void cancel()
{
2018-10-28 21:53:21 +01:00
std::unique_lock< std::mutex > lock( m_queueLock );
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
while( !m_queue.empty() )
{
T& value = m_queue.front();
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
deleteQueuedObject( value );
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
m_queue.pop();
}
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
m_shutdown = true;
2017-09-25 14:43:32 +02:00
2018-10-28 21:53:21 +01:00
m_condition.notify_all();
}
2018-10-28 21:53:21 +01:00
private:
template< typename E = T >
typename std::enable_if< std::is_pointer< E >::value >::type deleteQueuedObject( E& obj )
{
delete obj;
}
template< typename E = T >
typename std::enable_if< !std::is_pointer< E >::value >::type deleteQueuedObject( E const& )
{
}
};
2017-09-25 14:43:32 +02:00
}
#endif