// 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 #include #include #include "platform/assert.h" #include "platform/globals.h" // A queue backed by a circular buffer similar to dart:collection's ListQueue. template class ListQueue { public: static constexpr intptr_t kInitialCapacity = 64; ListQueue() : buffer_(std::make_unique(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 callback) const { for (intptr_t i = head_; i != tail_; i = (i + 1) % capacity_) { callback(buffer_[i]); } } private: std::unique_ptr 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 new_buffer = std::make_unique(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_