CrossThreadQueue.h [plain text]
#pragma once
#include <limits>
#include <wtf/Assertions.h>
#include <wtf/Condition.h>
#include <wtf/Deque.h>
#include <wtf/Lock.h>
#include <wtf/Noncopyable.h>
#include <wtf/Optional.h>
namespace WTF {
template<typename DataType>
class CrossThreadQueue final {
WTF_MAKE_FAST_ALLOCATED;
WTF_MAKE_NONCOPYABLE(CrossThreadQueue);
public:
CrossThreadQueue() = default;
void append(DataType&&);
DataType waitForMessage();
Optional<DataType> tryGetMessage();
void kill();
bool isKilled() const;
bool isEmpty() const;
private:
Deque<DataType> m_queue;
mutable Lock m_lock;
Condition m_condition;
bool m_killed { false };
};
template<typename DataType>
void CrossThreadQueue<DataType>::append(DataType&& message)
{
LockHolder lock(m_lock);
ASSERT(!m_killed);
m_queue.append(WTFMove(message));
m_condition.notifyOne();
}
template<typename DataType>
DataType CrossThreadQueue<DataType>::waitForMessage()
{
LockHolder lock(m_lock);
auto found = m_queue.end();
while (found == m_queue.end()) {
found = m_queue.begin();
if (found != m_queue.end())
break;
m_condition.wait(m_lock);
}
if (m_killed)
return { };
return m_queue.takeFirst();
}
template<typename DataType>
Optional<DataType> CrossThreadQueue<DataType>::tryGetMessage()
{
LockHolder lock(m_lock);
if (m_queue.isEmpty())
return { };
return m_queue.takeFirst();
}
template<typename DataType>
void CrossThreadQueue<DataType>::kill()
{
LockHolder lock(m_lock);
m_killed = true;
m_condition.notifyAll();
}
template<typename DataType>
bool CrossThreadQueue<DataType>::isKilled() const
{
LockHolder lock(m_lock);
return m_killed;
}
template<typename DataType>
bool CrossThreadQueue<DataType>::isEmpty() const
{
LockHolder lock(m_lock);
return m_queue.isEmpty();
}
}
using WTF::CrossThreadQueue;