Cuberite
A lightweight, fast and extensible game server for Minecraft
Queue.h
Go to the documentation of this file.
1 
2 // Queue.h
3 
4 // Implements the cQueue class representing a thread safe queue
5 
6 #pragma once
7 
8 /*
9 Items can be added multiple times to a queue, there are two functions for
10 adding, EnqueueItem() and EnqueueItemIfNotPresent(). The first one always
11 enqueues the specified item, the second one checks if the item is already
12 present and only queues it if it isn't.
13 
14 Usage:
15 To create a queue of type T, instantiate a cQueue<T> object. You can also
16 modify the behavior of the queue when deleting items and when adding items
17 that are already in the queue by providing a second parameter, a class that
18 implements the functions Delete() and Combine(). An example is given in
19 cQueueFuncs and is used as the default behavior. */
20 
22 template <class T>
24 {
25 public:
26 
28  static void Delete(T) {}
29 
31  static void Combine(T & a_existing, const T & a_new)
32  {
33  UNUSED(a_existing);
34  UNUSED(a_new);
35  }
36 };
37 
38 
39 
40 
41 
42 template <class ItemType, class Funcs = cQueueFuncs<ItemType> >
43 class cQueue
44 {
45  // The actual storage type for the queue
46  typedef typename std::list<ItemType> QueueType;
47 
48  // Make iterator an alias for the QueueType's iterator
49  typedef typename QueueType::iterator iterator;
50 
51 public:
52  cQueue() {}
53  ~cQueue() {}
54 
55 
57  void EnqueueItem(ItemType a_Item)
58  {
59  cCSLock Lock(m_CS);
60  m_Contents.push_back(a_Item);
61  m_evtAdded.Set();
62  }
63 
64 
66  void EnqueueItemIfNotPresent(ItemType a_Item)
67  {
68  cCSLock Lock(m_CS);
69 
70  for (iterator itr = m_Contents.begin(); itr != m_Contents.end(); ++itr)
71  {
72  if ((*itr) == a_Item)
73  {
74  Funcs::Combine(*itr, a_Item);
75  return;
76  }
77  }
78  m_Contents.push_back(a_Item);
79  m_evtAdded.Set();
80  }
81 
82 
85  bool TryDequeueItem(ItemType & item)
86  {
87  cCSLock Lock(m_CS);
88  if (m_Contents.empty())
89  {
90  return false;
91  }
92  item = m_Contents.front();
93  m_Contents.pop_front();
94  m_evtRemoved.Set();
95  return true;
96  }
97 
98 
100  ItemType DequeueItem(void)
101  {
102  cCSLock Lock(m_CS);
103  while (m_Contents.empty())
104  {
105  cCSUnlock Unlock(Lock);
106  m_evtAdded.Wait();
107  }
108  ItemType item = m_Contents.front();
109  m_Contents.pop_front();
110  m_evtRemoved.Set();
111  return item;
112  }
113 
114 
116  void BlockTillEmpty(void)
117  {
118  cCSLock Lock(m_CS);
119  while (!m_Contents.empty())
120  {
121  cCSUnlock Unlock(Lock);
122  m_evtRemoved.Wait();
123  }
124  }
125 
126 
128  void Clear(void)
129  {
130  cCSLock Lock(m_CS);
131  while (!m_Contents.empty())
132  {
133  Funcs::Delete(m_Contents.front());
134  m_Contents.pop_front();
135  }
136  }
137 
138 
141  size_t Size(void)
142  {
143  cCSLock Lock(m_CS);
144  return m_Contents.size();
145  }
146 
147 
150  bool Remove(ItemType a_Item)
151  {
152  cCSLock Lock(m_CS);
153  for (iterator itr = m_Contents.begin(); itr != m_Contents.end(); ++itr)
154  {
155  if ((*itr) == a_Item)
156  {
157  m_Contents.erase(itr);
158  m_evtRemoved.Set();
159  return true;
160  }
161  }
162  return false;
163  }
164 
165 
167  template <class Predicate>
168  void RemoveIf(Predicate a_Predicate)
169  {
170  cCSLock Lock(m_CS);
171  for (auto itr = m_Contents.begin(); itr != m_Contents.end();)
172  {
173  if (a_Predicate(*itr))
174  {
175  auto itr2 = itr;
176  ++itr2;
177  m_Contents.erase(itr);
178  m_evtRemoved.Set();
179  itr = itr2;
180  }
181  else
182  {
183  ++itr;
184  }
185  } // for itr - m_Contents[]
186  }
187 
188 private:
191 
194 
197 
200 };
201 
202 
203 
204 
#define UNUSED
Definition: Globals.h:72
RAII for cCriticalSection - locks the CS on creation, unlocks on destruction.
Temporary RAII unlock for a cCSLock.
Definition: Event.h:18
void Wait(void)
Waits until the event has been set.
Definition: Event.cpp:23
void Set(void)
Sets the event - releases one thread that has been waiting in Wait().
Definition: Event.cpp:52
This empty struct allows for the callback functions to be inlined.
Definition: Queue.h:24
static void Delete(T)
Called when an Item is deleted from the queue without being returned.
Definition: Queue.h:28
static void Combine(T &a_existing, const T &a_new)
Called when an Item is inserted with EnqueueItemIfNotPresent and there is another equal value already...
Definition: Queue.h:31
Definition: Queue.h:44
size_t Size(void)
Returns the size at time of being called.
Definition: Queue.h:141
cEvent m_evtRemoved
Event that is signalled when an item is removed (both dequeued or erased)
Definition: Queue.h:199
cCriticalSection m_CS
Mutex that protects access to the queue contents.
Definition: Queue.h:193
cEvent m_evtAdded
Event that is signalled when an item is added.
Definition: Queue.h:196
void EnqueueItemIfNotPresent(ItemType a_Item)
Enqueues an item in the queue if not already present (as determined by operator ==).
Definition: Queue.h:66
void EnqueueItem(ItemType a_Item)
Enqueues an item to the queue, may block if other threads are accessing the queue.
Definition: Queue.h:57
void Clear(void)
Removes all Items from the Queue, calling Delete on each of them.
Definition: Queue.h:128
std::list< ItemType > QueueType
Definition: Queue.h:46
QueueType m_Contents
The contents of the queue.
Definition: Queue.h:190
void RemoveIf(Predicate a_Predicate)
Removes all items for which the predicate returns true.
Definition: Queue.h:168
~cQueue()
Definition: Queue.h:53
QueueType::iterator iterator
Definition: Queue.h:49
void BlockTillEmpty(void)
Blocks until the queue is empty.
Definition: Queue.h:116
cQueue()
Definition: Queue.h:52
bool Remove(ItemType a_Item)
Removes the item from the queue.
Definition: Queue.h:150
ItemType DequeueItem(void)
Dequeues an item from the queue, blocking until an item is available.
Definition: Queue.h:100
bool TryDequeueItem(ItemType &item)
Dequeues an item from the queue if any are present.
Definition: Queue.h:85