| // 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_ |