47 class queue :
public interlockable
57 struct no_sink : std::logic_error {
no_sink() : std::logic_error(
"neolib::queue::no_sink") {} };
63 enum type_e { Send, Post };
66 entry(
const QueueItem& aItem, type_e aType) : iItem(aItem), iType(aType), iEvent(nullptr), iFrom(nullptr) {}
67 entry(
const QueueItem& aItem, type_e aType,
const event& aEvent) : iItem(aItem), iType(aType), iEvent(&aEvent), iFrom(nullptr) {}
68 entry(
const QueueItem& aItem, type_e aType,
const interlockable& aFrom) : iItem(aItem), iType(aType), iEvent(nullptr), iFrom(&aFrom) {}
69 entry(
const QueueItem& aItem, type_e aType,
const event& aEvent,
const interlockable& aFrom) : iItem(aItem), iType(aType), iEvent(&aEvent), iFrom(&aFrom) {}
72 const QueueItem& item()
const {
return iItem; }
73 QueueItem& item() {
return iItem; }
74 type_e type()
const {
return iType; }
75 const interlockable* from()
const {
return iFrom; }
76 void signal()
const {
if (iEvent !=
nullptr) iEvent->signal_one(); }
82 const interlockable* iFrom;
84 typedef std::list<entry> std_type;
85 typedef typename std_type::const_iterator const_iterator;
86 typedef typename std_type::iterator iterator;
87 typedef std::vector<iterator> working_list;
96 return iNewItemEvent.wait();
98 bool wait(uint32_t aTimeout_ms)
100 return iNewItemEvent.wait(aTimeout_ms);
102 void loop(
bool (*aYieldProc)() =
nullptr)
104 if (iSink ==
nullptr)
105 throw std::logic_error(
"neolib::queue::loop");
106 while (!aYieldProc || !aYieldProc())
112 void loop(uint32_t aTimeout_ms,
bool (*aYieldProc)() =
nullptr)
114 if (iSink ==
nullptr)
115 throw std::logic_error(
"neolib::queue::loop");
116 while ((!aYieldProc || !aYieldProc()) &&
wait(aTimeout_ms))
119 void send(
const QueueItem& aItem)
121 send(iProcessedItemEvent, aItem);
123 bool send(
const QueueItem& aItem, uint32_t aTimeout_ms)
125 return send(iProcessedItemEvent, aItem, aTimeout_ms);
130 iItems.push_back(entry(aItem, entry::Send, aEvent));
132 iNewItemEvent.signal();
133 return aEvent.wait();
135 bool send(
const event& aEvent,
const QueueItem& aItem, uint32_t aTimeout_ms)
138 iItems.push_back(entry(aItem, entry::Send, aEvent));
140 iNewItemEvent.signal();
141 return aEvent.timed_wait(aTimeout_ms);
147 bool interlocked_send(
const interlockable& aOther,
const QueueItem& aItem, uint32_t aTimeout_ms)
153 interlock_acquire(aOther);
155 iItems.push_back(entry(aItem, entry::Send, aEvent, aOther));
157 iNewItemEvent.signal_one();
158 interlock_release(aOther);
161 bool interlocked_send(
const interlockable& aOther,
const event& aEvent,
const QueueItem& aItem, uint32_t aTimeout_ms)
163 interlock_acquire(aOther);
165 iItems.push_back(entry(aItem, entry::Send, aEvent, aOther));
167 iNewItemEvent.signal_one();
168 interlock_release(aOther);
169 return aEvent.wait(aTimeout_ms);
171 void post(
const QueueItem& aItem)
174 iItems.push_back(entry(aItem, entry::Post));
176 iNewItemEvent.signal_one();
180 neolib::lock lock(*
this);
181 iterator nextEntry = next_available();
182 iWorkingList.push_back(nextEntry);
183 return nextEntry->item();
187 neolib::lock lock(*
this);
188 iterator nextEntry = iWorkingList.back();
189 iWorkingList.pop_back();
190 if (nextEntry->type() == entry::Send)
192 iItems.erase(nextEntry);
196 neolib::lock lock(*
this);
197 return next_available() != iItems.end();
201 neolib::lock lock(*
this);
209 if (iWorkingList.empty())
210 nextAvailable = iItems.begin();
213 nextAvailable = iWorkingList.back();
216 return nextAvailable;
218 iterator next_available()
220 iterator nextAvailable;
221 if (iWorkingList.empty())
222 nextAvailable = iItems.begin();
225 nextAvailable = iWorkingList.back();
228 return nextAvailable;
232 if (iSink ==
nullptr)
236 QueueItem& nextItem =
next();
242 virtual bool purge(
const interlockable& aOther)
244 if (iSink ==
nullptr)
245 throw std::logic_error(
"neolib::queue::purge");
246 neolib::lock lock(*
this);
247 for (working_list::const_iterator i = iWorkingList.begin(); i != iWorkingList.end(); ++i)
249 entry& theEntry = **i;
250 if (theEntry.type() == entry::Send && theEntry.from() == &aOther)
253 if (
wait(event::ShortTimeout_ms))
260 working_list iWorkingList;
262 event iProcessedItemEvent;