| // Copyright (c) 2025, the Dart project authors.  Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 |  | 
 | #ifndef RUNTIME_PLATFORM_LIST_QUEUE_H_ | 
 | #define RUNTIME_PLATFORM_LIST_QUEUE_H_ | 
 |  | 
 | #include <functional> | 
 | #include <memory> | 
 | #include <utility> | 
 |  | 
 | #include "platform/assert.h" | 
 | #include "platform/globals.h" | 
 |  | 
 | // A queue backed by a circular buffer similar to dart:collection's ListQueue. | 
 | template <typename T> | 
 | class ListQueue { | 
 |  public: | 
 |   static constexpr intptr_t kInitialCapacity = 64; | 
 |  | 
 |   ListQueue() | 
 |       : buffer_(std::make_unique<T[]>(kInitialCapacity)), | 
 |         capacity_(kInitialCapacity) {} | 
 |  | 
 |   void PushBack(T&& element) { | 
 |     buffer_[tail_] = std::move(element); | 
 |     tail_ = (tail_ + 1) % capacity_; | 
 |     if (head_ == tail_) { | 
 |       Grow(); | 
 |     } | 
 |     ++length_; | 
 |   } | 
 |  | 
 |   T&& PopFront() { | 
 |     ASSERT(head_ != tail_); | 
 |     T&& element = std::move(buffer_[head_]); | 
 |     head_ = (head_ + 1) % capacity_; | 
 |     --length_; | 
 |     return std::move(element); | 
 |   } | 
 |  | 
 |   // The number of elements currently in the queue. | 
 |   intptr_t Length() { return length_; } | 
 |  | 
 |   void ForEach(std::function<void(const T&)> callback) const { | 
 |     for (intptr_t i = head_; i != tail_; i = (i + 1) % capacity_) { | 
 |       callback(buffer_[i]); | 
 |     } | 
 |   } | 
 |  | 
 |  private: | 
 |   std::unique_ptr<T[]> buffer_; | 
 |   intptr_t capacity_; | 
 |   intptr_t length_ = 0; | 
 |   intptr_t head_ = 0; | 
 |   intptr_t tail_ = 0; | 
 |  | 
 |   void Grow() { | 
 |     intptr_t split = capacity_ - head_; | 
 |  | 
 |     intptr_t new_capacity = capacity_ << 1; | 
 |     std::unique_ptr<T[]> new_buffer = std::make_unique<T[]>(new_capacity); | 
 |  | 
 |     for (intptr_t i = 0; i < split; ++i) { | 
 |       new_buffer[i] = std::move(buffer_[head_ + i]); | 
 |     } | 
 |     for (intptr_t i = split; i < split + head_; ++i) { | 
 |       new_buffer[i] = std::move(buffer_[i - split]); | 
 |     } | 
 |  | 
 |     head_ = 0; | 
 |     tail_ = capacity_; | 
 |     buffer_.swap(new_buffer); | 
 |     capacity_ = new_capacity; | 
 |   } | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(ListQueue); | 
 | }; | 
 |  | 
 | #endif  // RUNTIME_PLATFORM_LIST_QUEUE_H_ |