Skip to content

Commit 416c44b

Browse files
committed
curve: Simplify queue operations.
1 parent 6a92ae5 commit 416c44b

File tree

1 file changed

+38
-26
lines changed

1 file changed

+38
-26
lines changed

libopenage/curve/queue.h

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class Queue : public event::EventEntity {
7474
/**
7575
* The iterator type to access elements in the container
7676
*/
77+
using const_iterator = typename container_t::const_iterator;
7778
using iterator = typename container_t::iterator;
7879

7980
Queue(const std::shared_ptr<event::EventLoop> &loop,
@@ -220,12 +221,15 @@ class Queue : public event::EventEntity {
220221

221222
private:
222223
/**
223-
* Erase an element from the queue at the given time.
224+
* Kill an element from the queue at the given time.
224225
*
225-
* @param time The time to erase at.
226-
* @param at The index of the element to erase.
226+
* The element is set to dead at the given time and is not accessible
227+
* for pops with t > time.
228+
*
229+
* @param time The time to kill at.
230+
* @param at The index of the element to kill.
227231
*/
228-
void erase(const time::time_t &time, index_t at);
232+
void kill(const time::time_t &time, index_t at);
229233

230234
/**
231235
* Get the first alive element inserted at t <= time.
@@ -274,6 +278,7 @@ typename Queue<T>::index_t Queue<T>::first_alive(const time::time_t &time) const
274278
// start searching from the last front position
275279
hint = this->front_start;
276280
}
281+
// else search from the beginning
277282

278283
// Iterate until we find an alive element
279284
while (hint != this->container.size()
@@ -290,24 +295,38 @@ typename Queue<T>::index_t Queue<T>::first_alive(const time::time_t &time) const
290295

291296
template <typename T>
292297
const T &Queue<T>::front(const time::time_t &time) const {
293-
auto at = this->first_alive(time);
294-
ENSURE(at != this->container.size(), "Tried accessing front at " << time << " but queue is empty.");
298+
index_t at = this->first_alive(time);
299+
ENSURE(at < this->container.size(),
300+
"Tried accessing front at " << time << " but index " << at << " is invalid. "
301+
<< "The queue may be empty."
302+
<< "(last_change: " << this->last_change
303+
<< ", front_start: " << this->front_start
304+
<< ", container size: " << this->container.size()
305+
<< ")");
295306

296307
return this->container.at(at).value;
297308
}
298309

299310

300311
template <class T>
301312
const T &Queue<T>::pop_front(const time::time_t &time) {
302-
auto at = this->first_alive(time);
303-
ENSURE(at != this->container.size(), "Tried accessing front at " << time << " but queue is empty.");
313+
index_t at = this->first_alive(time);
314+
ENSURE(at < this->container.size(),
315+
"Tried accessing front at " << time << " but index " << at << " is invalid. "
316+
<< "The queue may be empty."
317+
<< "(last_change: " << this->last_change
318+
<< ", front_start: " << this->front_start
319+
<< ", container size: " << this->container.size()
320+
<< ")");
321+
322+
// kill the element at time t
323+
this->kill(time, at);
304324

305325
// cache the search start position for the next front() call
306-
this->front_start = at;
326+
// for pop time t, there should be no more elements alive before t
327+
// so we can advance the front to the next element
307328
this->last_change = time;
308-
309-
// erase the element
310-
this->erase(time, at);
329+
this->front_start = at + 1;
311330

312331
this->changes(time);
313332

@@ -373,8 +392,8 @@ void Queue<T>::erase(const CurveIterator<T, Queue<T>> &it) {
373392

374393

375394
template <class T>
376-
void Queue<T>::erase(const time::time_t &time,
377-
index_t at) {
395+
void Queue<T>::kill(const time::time_t &time,
396+
index_t at) {
378397
this->container[at].set_dead(time);
379398
}
380399

@@ -383,7 +402,7 @@ template <typename T>
383402
QueueFilterIterator<T, Queue<T>> Queue<T>::insert(const time::time_t &time,
384403
const T &e) {
385404
index_t at = this->container.size();
386-
while (at != 0) {
405+
while (at > 0) {
387406
--at;
388407
if (this->container.at(at).alive() <= time) {
389408
++at;
@@ -400,19 +419,12 @@ QueueFilterIterator<T, Queue<T>> Queue<T>::insert(const time::time_t &time,
400419

401420
// cache the insertion time
402421
this->last_change = time;
403-
if (this->front_start == this->container.size()) [[unlikely]] {
404-
// only true if the container is empty
405-
// or all elements are dead
422+
423+
// if the new element is inserted before the current front element
424+
// cache it as the new front element
425+
if (at < this->front_start) {
406426
this->front_start = at;
407427
}
408-
else {
409-
// if there are more alive elements, only cache if the
410-
// insertion time is before the current front
411-
if (time < this->container.at(this->front_start).alive()) {
412-
// cache the search start position for the next front() call
413-
this->front_start = at;
414-
}
415-
}
416428

417429
auto ct = QueueFilterIterator<T, Queue<T>>(
418430
insertion_point,

0 commit comments

Comments
 (0)