From 63e46abdb8764bc97e91bae862c8d461e61b1965 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 8 Apr 2014 19:25:03 -0400 Subject: got rid of 'src' folders in each sub-project --- src/common/fifo_queue.h | 115 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 src/common/fifo_queue.h (limited to 'src/common/fifo_queue.h') diff --git a/src/common/fifo_queue.h b/src/common/fifo_queue.h new file mode 100644 index 000000000..57efcd839 --- /dev/null +++ b/src/common/fifo_queue.h @@ -0,0 +1,115 @@ + +#ifndef _FIFO_QUEUE_H_ +#define _FIFO_QUEUE_H_ + +// a simple lockless thread-safe, +// single reader, single writer queue + +#include "atomic.h" + +namespace Common +{ + +template +class FifoQueue +{ +public: + FifoQueue() : m_size(0) + { + m_write_ptr = m_read_ptr = new ElementPtr(); + } + + ~FifoQueue() + { + // this will empty out the whole queue + delete m_read_ptr; + } + + u32 Size() const + { + return m_size; + } + + bool Empty() const + { + //return (m_read_ptr == m_write_ptr); + return (0 == m_size); + } + + T& Front() const + { + return *m_read_ptr->current; + } + + template + void Push(Arg&& t) + { + // create the element, add it to the queue + m_write_ptr->current = new T(std::forward(t)); + // set the next pointer to a new element ptr + // then advance the write pointer + m_write_ptr = m_write_ptr->next = new ElementPtr(); + Common::AtomicIncrement(m_size); + } + + void Pop() + { + Common::AtomicDecrement(m_size); + ElementPtr *const tmpptr = m_read_ptr; + // advance the read pointer + m_read_ptr = m_read_ptr->next; + // set the next element to NULL to stop the recursive deletion + tmpptr->next = NULL; + delete tmpptr; // this also deletes the element + } + + bool Pop(T& t) + { + if (Empty()) + return false; + + t = std::move(Front()); + Pop(); + + return true; + } + + // not thread-safe + void Clear() + { + m_size = 0; + delete m_read_ptr; + m_write_ptr = m_read_ptr = new ElementPtr(); + } + +private: + // stores a pointer to element + // and a pointer to the next ElementPtr + class ElementPtr + { + public: + ElementPtr() : current(NULL), next(NULL) {} + + ~ElementPtr() + { + if (current) + { + delete current; + // recusion ftw + if (next) + delete next; + } + } + + T *volatile current; + ElementPtr *volatile next; + }; + + ElementPtr *volatile m_write_ptr; + ElementPtr *volatile m_read_ptr; + volatile u32 m_size; +}; + +} + +#endif -- cgit v1.2.3