blob: 69d75c0a212eba2a679df305cb5eb21a9b3b8776 [file] [log] [blame] [edit]
// 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_