Implements chre::ArrayQueue::clear

Bug: 110787653
Test: run_tests.sh
Change-Id: I3b12ce042abb47f88b9d8caabb6faeea0855d0a2
diff --git a/util/include/chre/util/array_queue.h b/util/include/chre/util/array_queue.h
index db70634..2ff6e7a 100644
--- a/util/include/chre/util/array_queue.h
+++ b/util/include/chre/util/array_queue.h
@@ -146,6 +146,11 @@
   bool emplace(Args&&... args);
 
   /**
+   * Removes all the elements of the queue.
+   */
+  void clear();
+
+  /**
    * A template class that implements a forward iterator for the array queue.
    */
   template<typename ValueType>
diff --git a/util/include/chre/util/array_queue_impl.h b/util/include/chre/util/array_queue_impl.h
index d3ba2e8..0de6341 100644
--- a/util/include/chre/util/array_queue_impl.h
+++ b/util/include/chre/util/array_queue_impl.h
@@ -27,9 +27,7 @@
 
 template<typename ElementType, size_t kCapacity>
 ArrayQueue<ElementType, kCapacity>::~ArrayQueue() {
-  while (!empty()) {
-    pop();
-  }
+  clear();
 }
 
 template<typename ElementType, size_t kCapacity>
@@ -166,6 +164,19 @@
 }
 
 template<typename ElementType, size_t kCapacity>
+void ArrayQueue<ElementType, kCapacity>::clear() {
+  if (!std::is_trivially_destructible<ElementType>::value) {
+    while (!empty()) {
+      pop();
+    }
+  } else {
+    mSize = 0;
+    mHead = 0;
+    mTail = kCapacity - 1;
+  }
+}
+
+template<typename ElementType, size_t kCapacity>
 typename ArrayQueue<ElementType, kCapacity>::iterator
 ArrayQueue<ElementType, kCapacity>::begin() {
   // Align begin() and end() outside of the memory block when empty.
diff --git a/util/tests/array_queue_test.cc b/util/tests/array_queue_test.cc
index 8dd631e..3f425ce 100644
--- a/util/tests/array_queue_test.cc
+++ b/util/tests/array_queue_test.cc
@@ -11,6 +11,7 @@
 constexpr int kMaxTestCapacity = 10;
 int destructor_count[kMaxTestCapacity];
 int constructor_count;
+int total_destructor_count;
 
 class DummyElement {
  public:
@@ -22,6 +23,7 @@
     constructor_count++;
   };
   ~DummyElement() {
+    total_destructor_count++;
     if (val_ >= 0 && val_ < kMaxTestCapacity) {
       destructor_count[val_]++;
     }
@@ -466,3 +468,44 @@
       std::is_same<traits::iterator_category, std::forward_iterator_tag>::value,
       "ArrayQueueIterator should be a forward iterator");
 }
+
+TEST(ArrayQueueTest, ArrayClear) {
+  ArrayQueue<size_t, 4> q;
+
+  q.clear();
+  EXPECT_TRUE(q.empty());
+
+  for (size_t i = 0; i < 4; i++) {
+    q.push(i);
+  }
+
+  q.clear();
+  EXPECT_TRUE(q.empty());
+
+  // Make sure that insertion/access still work after a clear.
+  for (size_t i = 0; i < 4; i++) {
+    q.push(i);
+  }
+  for (size_t i = 0; i < 4; i++) {
+    EXPECT_EQ(q[i], i);
+  }
+}
+
+TEST(ArrayQueueTest, ElementsDestructedArrayClear) {
+  for (size_t i = 0; i < kMaxTestCapacity; ++i) {
+    destructor_count[i] = 0;
+  }
+  total_destructor_count = 0;
+
+  ArrayQueue<DummyElement, 4> q;
+  for (size_t i = 0; i < 3; ++i) {
+    q.emplace(i);
+  }
+
+  q.clear();
+
+  for (size_t i = 0; i < 3; ++i) {
+    EXPECT_EQ(1, destructor_count[i]);
+  }
+  EXPECT_EQ(3, total_destructor_count);
+}