From: Giacomo Travaglini Date: Fri, 8 Mar 2019 16:01:20 +0000 (+0000) Subject: base: Fix CircularQueue when diffing iterators X-Git-Tag: v19.0.0.0~1023 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=bbcbde7a924ca1ca58df997cfe9f750c285e5564;p=gem5.git base: Fix CircularQueue when diffing iterators This patch is fixing CircularQueue iterators' subtraction, in particular the behaviour when head and tail round multiple times. Change-Id: Ie79ac8accd30a10cf039cf4def87675b01375d6b Signed-off-by: Giacomo Travaglini Reviewed-by: Gabor Dozsa Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/17188 Reviewed-by: Daniel Carvalho Reviewed-by: Jason Lowe-Power Maintainer: Andreas Sandberg --- diff --git a/src/base/circular_queue.hh b/src/base/circular_queue.hh index 5023661b9..f368ed0d1 100644 --- a/src/base/circular_queue.hh +++ b/src/base/circular_queue.hh @@ -106,10 +106,19 @@ class CircularQueue : private std::vector static uint32_t moduloSub(uint32_t op1, uint32_t op2, uint32_t size) { - int ret = (uint32_t)(op1 - op2) % size; + int32_t ret = sub(op1, op2, size); return ret >= 0 ? ret : ret + size; } + static int32_t + sub(uint32_t op1, uint32_t op2, uint32_t size) + { + if (op1 > op2) + return (op1 - op2) % size; + else + return -((op2 - op1) % size); + } + void increase(uint32_t& v, size_t delta = 1) { v = moduloAdd(v, delta, _capacity); @@ -355,10 +364,10 @@ class CircularQueue : private std::vector difference_type operator-(const iterator& that) { /* If a is already at the end, we can safely return 0. */ - auto ret = _cq->moduloSub(this->_idx, that._idx); + auto ret = _cq->sub(this->_idx, that._idx, _cq->capacity()); - if (ret == 0 && this->_round != that._round) { - ret += this->_round * _cq->capacity(); + if (this->_round != that._round) { + ret += ((this->_round - that._round) * _cq->capacity()); } return ret; } diff --git a/src/base/circular_queue.test.cc b/src/base/circular_queue.test.cc index db59c3049..cce6cb0b6 100644 --- a/src/base/circular_queue.test.cc +++ b/src/base/circular_queue.test.cc @@ -212,6 +212,7 @@ TEST(CircularQueueTest, IteratorsOp) ASSERT_EQ(it_1 + 1, it_2); ASSERT_EQ(it_1, it_2 - 1); ASSERT_EQ(it_2 - it_1, 1); + ASSERT_EQ(it_1 - it_2, -1); auto temp_it = it_1; ASSERT_EQ(++temp_it, it_2); @@ -241,3 +242,27 @@ TEST(CircularQueueTest, FullLoop) ASSERT_EQ(starting_it._idx, ending_it._idx); ASSERT_TRUE(starting_it != ending_it); } + +/** + * Testing correct behaviour when rounding multiple times: + * - Round indexes in sync + * - Difference between begin() and end() iterator is still + * equal to the CircularQueue size. + */ +TEST(CircularQueueTest, MultipleRound) +{ + const auto cq_size = 8; + CircularQueue cq(cq_size); + + // Filling the queue making it round multiple times + auto items_added = cq_size * 3; + for (auto idx = 0; idx < items_added; idx++) { + cq.push_back(0); + } + + auto starting_it = cq.begin(); + auto ending_it = cq.end(); + + ASSERT_EQ(starting_it._round + 1, ending_it._round); + ASSERT_EQ(ending_it - starting_it, cq_size); +}