summaryrefslogtreecommitdiff
path: root/src/common/fifo_queue.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/fifo_queue.h')
-rw-r--r--src/common/fifo_queue.h115
1 files changed, 115 insertions, 0 deletions
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 @@
1
2#ifndef _FIFO_QUEUE_H_
3#define _FIFO_QUEUE_H_
4
5// a simple lockless thread-safe,
6// single reader, single writer queue
7
8#include "atomic.h"
9
10namespace Common
11{
12
13template <typename T>
14class FifoQueue
15{
16public:
17 FifoQueue() : m_size(0)
18 {
19 m_write_ptr = m_read_ptr = new ElementPtr();
20 }
21
22 ~FifoQueue()
23 {
24 // this will empty out the whole queue
25 delete m_read_ptr;
26 }
27
28 u32 Size() const
29 {
30 return m_size;
31 }
32
33 bool Empty() const
34 {
35 //return (m_read_ptr == m_write_ptr);
36 return (0 == m_size);
37 }
38
39 T& Front() const
40 {
41 return *m_read_ptr->current;
42 }
43
44 template <typename Arg>
45 void Push(Arg&& t)
46 {
47 // create the element, add it to the queue
48 m_write_ptr->current = new T(std::forward<Arg>(t));
49 // set the next pointer to a new element ptr
50 // then advance the write pointer
51 m_write_ptr = m_write_ptr->next = new ElementPtr();
52 Common::AtomicIncrement(m_size);
53 }
54
55 void Pop()
56 {
57 Common::AtomicDecrement(m_size);
58 ElementPtr *const tmpptr = m_read_ptr;
59 // advance the read pointer
60 m_read_ptr = m_read_ptr->next;
61 // set the next element to NULL to stop the recursive deletion
62 tmpptr->next = NULL;
63 delete tmpptr; // this also deletes the element
64 }
65
66 bool Pop(T& t)
67 {
68 if (Empty())
69 return false;
70
71 t = std::move(Front());
72 Pop();
73
74 return true;
75 }
76
77 // not thread-safe
78 void Clear()
79 {
80 m_size = 0;
81 delete m_read_ptr;
82 m_write_ptr = m_read_ptr = new ElementPtr();
83 }
84
85private:
86 // stores a pointer to element
87 // and a pointer to the next ElementPtr
88 class ElementPtr
89 {
90 public:
91 ElementPtr() : current(NULL), next(NULL) {}
92
93 ~ElementPtr()
94 {
95 if (current)
96 {
97 delete current;
98 // recusion ftw
99 if (next)
100 delete next;
101 }
102 }
103
104 T *volatile current;
105 ElementPtr *volatile next;
106 };
107
108 ElementPtr *volatile m_write_ptr;
109 ElementPtr *volatile m_read_ptr;
110 volatile u32 m_size;
111};
112
113}
114
115#endif