summaryrefslogtreecommitdiffstats
path: root/src/OSSupport/Queue.h
diff options
context:
space:
mode:
authorTycho <work.tycho+git@gmail.com>2014-01-04 13:03:41 +0100
committerTycho <work.tycho+git@gmail.com>2014-01-04 13:03:41 +0100
commitf0b35930281ba292adaeddfe95dc833533dfc874 (patch)
tree0aab046a47fa9d39f09561744fff8bbfbbc27230 /src/OSSupport/Queue.h
parentremoved tolua++ makefile which is overwritten by cmake (diff)
parentMerge pull request #494 from worktycho/threadsafequeue (diff)
downloadcuberite-f0b35930281ba292adaeddfe95dc833533dfc874.tar
cuberite-f0b35930281ba292adaeddfe95dc833533dfc874.tar.gz
cuberite-f0b35930281ba292adaeddfe95dc833533dfc874.tar.bz2
cuberite-f0b35930281ba292adaeddfe95dc833533dfc874.tar.lz
cuberite-f0b35930281ba292adaeddfe95dc833533dfc874.tar.xz
cuberite-f0b35930281ba292adaeddfe95dc833533dfc874.tar.zst
cuberite-f0b35930281ba292adaeddfe95dc833533dfc874.zip
Diffstat (limited to '')
-rw-r--r--src/OSSupport/Queue.h156
1 files changed, 138 insertions, 18 deletions
diff --git a/src/OSSupport/Queue.h b/src/OSSupport/Queue.h
index 4571272b3..cde26e415 100644
--- a/src/OSSupport/Queue.h
+++ b/src/OSSupport/Queue.h
@@ -1,31 +1,151 @@
+
+// Queue.h
+
+// Implements the cQueue class representing a thread safe queue
+
#pragma once
+/*
+Items can be added multiple times to a queue, there are two functions for
+adding, EnqueueItem() and EnqueueItemIfNotPresent(). The first one always
+enqueues the specified item, the second one checks if the item is already
+present and only queues it if it isn't.
+
+Usage:
+To create a queue of type T, instantiate a cQueue<T> object. You can also
+modify the behavior of the queue when deleting items and when adding items
+that are already in the queue by providing a second parameter, a class that
+implements the functions Delete() and Combine(). An example is given in
+cQueueFuncs and is used as the default behavior.
+*/
+
+// this empty struct allows for the callback functions to be inlined
template<class T>
-class cDeleter
+struct cQueueFuncs
{
public:
+ // Called when an Item is deleted form the queue without being returned
static void Delete(T) {};
+ // Called when an Item is inserted with EnqueueItemIfNotPresent and
+ // there is another equal value already inserted
+ static void Combine(T& a_existing, const T& a_new) {};
};
-template<class T, class D = cDeleter<T>>
+template<class ItemType, class Funcs = cQueueFuncs<ItemType> >
class cQueue
{
+// internal typedef for a List of Items
+typedef typename std::list<ItemType> ListType;
+// magic typedef to persuade clang that the iterator is a type
+typedef typename ListType::iterator iterator;
public:
- cQueue(int warnsize);
- cQueue(cQueue<T>& queue);
- ~cQueue();
-
- void EnqueueItem(T item);
- bool TryDequeueItem(T& item);
- T DequeueItem();
- void BlockTillEmpty(cEvent CancelationEvent);
- void Clear();
- int Size();
-
+ cQueue() {}
+ ~cQueue() {}
+
+ // Enqueues an item to the queue, may block if other threads are accessing
+ // the queue.
+ void EnqueueItem(ItemType a_item)
+ {
+ cCSLock Lock(m_CS);
+ m_contents.push_back(a_item);
+ m_evtAdded.Set();
+ }
+
+ // Enqueues an item to the queue if not already present as determined with
+ // operator ==. Will block other threads from accessing the queue.
+ 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();
+ }
+
+ // Dequeues an Item from the queue if any are present. Returns true if
+ // successful. Value of item is undefined if Dequeuing was unsuccessful.
+ bool TryDequeueItem(ItemType& item)
+ {
+ cCSLock Lock(m_CS);
+ if (m_contents.size() == 0)
+ {
+ return false;
+ }
+ item = m_contents.front();
+ m_contents.pop_front();
+ m_evtRemoved.Set();
+ return true;
+ }
+
+ // Dequeues an Item from the Queue, blocking until an Item is Available.
+ ItemType DequeueItem()
+ {
+ cCSLock Lock(m_CS);
+ while (m_contents.size() == 0)
+ {
+ cCSUnlock Unlock(m_CS);
+ m_evtAdded.Wait();
+ }
+ ItemType item = m_contents.front();
+ m_contents.pop_front();
+ m_evtRemoved.Set();
+ return item;
+ }
+
+ // Blocks Until the queue is Empty, Has a slight race condition which may
+ // cause it to miss the queue being empty.
+ 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();}
+ }
+
+ // Removes all Items from the Queue, calling Delete on each of them.
+ // 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();
+ }
+ }
+
+ // Returns the Size at time of being called
+ // Do not use to detirmine weather to call DequeueItem, use TryDequeue instead
+ size_t Size()
+ {
+ cCSLock Lock(m_CS);
+ return m_contents.size();
+ }
+
+ // Removes an Item from the queue
+ bool Remove(ItemType a_item)
+ {
+ cCSLock Lock(m_CS);
+ for (iterator itr = m_contents.begin(); itr != m_contents.end(); ++itr)
+ {
+ if((*itr) == a_item) {
+ m_contents.erase(itr);
+ m_evtRemoved.Set();
+ return true;
+ }
+ }
+ return false;
+ }
+
private:
- int warnsize;
- std::list<T> contents;
+ ListType m_contents;
+ cCriticalSection m_CS;
+ cEvent m_evtAdded;
+ cEvent m_evtRemoved;
};
-
-//template classes must be implemented in the header
-#include "Queue.inc"