2013-12-31 15:48:57 +00:00
|
|
|
|
2013-12-21 14:43:32 +00:00
|
|
|
#pragma once
|
|
|
|
|
2013-12-31 15:48:57 +00:00
|
|
|
#include <list>
|
|
|
|
|
|
|
|
//this empty struct allows function inlining
|
2013-12-21 14:43:32 +00:00
|
|
|
template<class T>
|
2013-12-31 15:48:57 +00:00
|
|
|
struct cQueueFuncs
|
2013-12-21 14:43:32 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
static void Delete(T) {};
|
2013-12-31 15:48:57 +00:00
|
|
|
static void Combine(T&, const T) {};
|
|
|
|
};
|
2013-12-21 14:43:32 +00:00
|
|
|
|
2013-12-31 15:48:57 +00:00
|
|
|
template<class ItemType, class Funcs = cQueueFuncs<ItemType> >
|
2013-12-21 14:43:32 +00:00
|
|
|
class cQueue
|
|
|
|
{
|
2013-12-31 15:48:57 +00:00
|
|
|
|
|
|
|
typedef typename std::list<ItemType> ListType;
|
|
|
|
//magic typedef to persuade clang that the iterator is a type
|
|
|
|
typedef typename ListType::iterator iterator;
|
2013-12-21 14:43:32 +00:00
|
|
|
public:
|
2013-12-31 15:48:57 +00:00
|
|
|
cQueue() {}
|
|
|
|
~cQueue() {}
|
|
|
|
|
|
|
|
void EnqueueItem(ItemType a_item)
|
|
|
|
{
|
|
|
|
cCSLock Lock(m_CS);
|
|
|
|
m_contents.push_back(a_item);
|
|
|
|
m_evtAdded.Set();
|
|
|
|
}
|
|
|
|
void EnqueueItemIfNotPresent(ItemType a_item)
|
|
|
|
{
|
|
|
|
cCSLock Lock(m_CS);
|
|
|
|
|
|
|
|
for (iterator itr = m_contents.begin(); itr != m_contents.end(); ++itr)
|
|
|
|
{
|
|
|
|
if((*itr) == a_item) {
|
|
|
|
Funcs funcTable;
|
|
|
|
funcTable.Combine(*itr,a_item);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_contents.push_back(a_item);
|
|
|
|
m_evtAdded.Set();
|
|
|
|
}
|
|
|
|
bool TryDequeueItem(ItemType& item)
|
|
|
|
{
|
|
|
|
cCSLock Lock(m_CS);
|
|
|
|
if (m_contents.size() == 0) return false;
|
|
|
|
item = m_contents.front();
|
|
|
|
m_contents.pop_front();
|
2014-01-02 12:32:55 +00:00
|
|
|
m_evtRemoved.Set();
|
2013-12-31 15:48:57 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
ItemType DequeueItem()
|
|
|
|
{
|
|
|
|
cCSLock Lock(m_CS);
|
|
|
|
while (m_contents.size() == 0)
|
|
|
|
{
|
|
|
|
cCSUnlock Unlock(m_CS);
|
|
|
|
m_evtAdded.Wait();
|
|
|
|
}
|
2014-01-02 12:32:55 +00:00
|
|
|
ItemType item = m_contents.front();
|
|
|
|
m_contents.pop_front();
|
|
|
|
m_evtRemoved.Set();
|
|
|
|
return item;
|
2013-12-31 15:48:57 +00:00
|
|
|
}
|
2014-01-02 12:32:55 +00:00
|
|
|
void BlockTillEmpty() {
|
|
|
|
//There is a very slight race condition here if the load completes between the check
|
|
|
|
//and the wait.
|
|
|
|
while(!(Size() == 0)){m_evtRemoved.Wait();}
|
2013-12-31 15:48:57 +00:00
|
|
|
}
|
|
|
|
//can all be inlined when delete is a noop
|
|
|
|
void Clear()
|
|
|
|
{
|
|
|
|
cCSLock Lock(m_CS);
|
|
|
|
Funcs funcTable;
|
|
|
|
while (!m_contents.empty())
|
|
|
|
{
|
|
|
|
funcTable.Delete(m_contents.front());
|
|
|
|
m_contents.pop_front();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
size_t Size()
|
|
|
|
{
|
|
|
|
cCSLock Lock(m_CS);
|
|
|
|
return m_contents.size();
|
|
|
|
}
|
|
|
|
bool Remove(ItemType item)
|
|
|
|
{
|
|
|
|
cCSLock Lock(m_CS);
|
|
|
|
m_contents.remove(item);
|
2014-01-02 12:32:55 +00:00
|
|
|
m_evtRemoved.Set();
|
2013-12-31 15:48:57 +00:00
|
|
|
}
|
|
|
|
|
2013-12-21 14:43:32 +00:00
|
|
|
private:
|
2013-12-31 15:48:57 +00:00
|
|
|
ListType m_contents;
|
|
|
|
cCriticalSection m_CS;
|
|
|
|
cEvent m_evtAdded;
|
2014-01-02 12:32:55 +00:00
|
|
|
cEvent m_evtRemoved;
|
2013-12-31 15:48:57 +00:00
|
|
|
};
|