1*09537850SAkhilesh Sanikop /* 2*09537850SAkhilesh Sanikop * Copyright 2019 The libgav1 Authors 3*09537850SAkhilesh Sanikop * 4*09537850SAkhilesh Sanikop * Licensed under the Apache License, Version 2.0 (the "License"); 5*09537850SAkhilesh Sanikop * you may not use this file except in compliance with the License. 6*09537850SAkhilesh Sanikop * You may obtain a copy of the License at 7*09537850SAkhilesh Sanikop * 8*09537850SAkhilesh Sanikop * http://www.apache.org/licenses/LICENSE-2.0 9*09537850SAkhilesh Sanikop * 10*09537850SAkhilesh Sanikop * Unless required by applicable law or agreed to in writing, software 11*09537850SAkhilesh Sanikop * distributed under the License is distributed on an "AS IS" BASIS, 12*09537850SAkhilesh Sanikop * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*09537850SAkhilesh Sanikop * See the License for the specific language governing permissions and 14*09537850SAkhilesh Sanikop * limitations under the License. 15*09537850SAkhilesh Sanikop */ 16*09537850SAkhilesh Sanikop 17*09537850SAkhilesh Sanikop #ifndef LIBGAV1_SRC_UTILS_QUEUE_H_ 18*09537850SAkhilesh Sanikop #define LIBGAV1_SRC_UTILS_QUEUE_H_ 19*09537850SAkhilesh Sanikop 20*09537850SAkhilesh Sanikop #include <cassert> 21*09537850SAkhilesh Sanikop #include <cstddef> 22*09537850SAkhilesh Sanikop #include <memory> 23*09537850SAkhilesh Sanikop #include <new> 24*09537850SAkhilesh Sanikop #include <utility> 25*09537850SAkhilesh Sanikop 26*09537850SAkhilesh Sanikop #include "src/utils/compiler_attributes.h" 27*09537850SAkhilesh Sanikop 28*09537850SAkhilesh Sanikop namespace libgav1 { 29*09537850SAkhilesh Sanikop 30*09537850SAkhilesh Sanikop // A FIFO queue of a fixed capacity. 31*09537850SAkhilesh Sanikop // 32*09537850SAkhilesh Sanikop // WARNING: No error checking is performed. 33*09537850SAkhilesh Sanikop template <typename T> 34*09537850SAkhilesh Sanikop class Queue { 35*09537850SAkhilesh Sanikop public: Init(size_t capacity)36*09537850SAkhilesh Sanikop LIBGAV1_MUST_USE_RESULT bool Init(size_t capacity) { 37*09537850SAkhilesh Sanikop elements_.reset(new (std::nothrow) T[capacity]); 38*09537850SAkhilesh Sanikop if (elements_ == nullptr) return false; 39*09537850SAkhilesh Sanikop capacity_ = capacity; 40*09537850SAkhilesh Sanikop return true; 41*09537850SAkhilesh Sanikop } 42*09537850SAkhilesh Sanikop 43*09537850SAkhilesh Sanikop // Pushes the element |value| to the end of the queue. It is an error to call 44*09537850SAkhilesh Sanikop // Push() when the queue is full. Push(T && value)45*09537850SAkhilesh Sanikop void Push(T&& value) { 46*09537850SAkhilesh Sanikop assert(size_ < capacity_); 47*09537850SAkhilesh Sanikop elements_[end_++] = std::move(value); 48*09537850SAkhilesh Sanikop if (end_ == capacity_) end_ = 0; 49*09537850SAkhilesh Sanikop ++size_; 50*09537850SAkhilesh Sanikop } 51*09537850SAkhilesh Sanikop 52*09537850SAkhilesh Sanikop // Removes the element at the front of the queue. It is an error to call Pop() 53*09537850SAkhilesh Sanikop // when the queue is empty. Pop()54*09537850SAkhilesh Sanikop void Pop() { 55*09537850SAkhilesh Sanikop assert(size_ != 0); 56*09537850SAkhilesh Sanikop const T element = std::move(elements_[begin_++]); 57*09537850SAkhilesh Sanikop static_cast<void>(element); 58*09537850SAkhilesh Sanikop if (begin_ == capacity_) begin_ = 0; 59*09537850SAkhilesh Sanikop --size_; 60*09537850SAkhilesh Sanikop } 61*09537850SAkhilesh Sanikop 62*09537850SAkhilesh Sanikop // Returns a reference to the element at the front of the queue. It is an 63*09537850SAkhilesh Sanikop // error to call Front() when the queue is empty. Front()64*09537850SAkhilesh Sanikop T& Front() { 65*09537850SAkhilesh Sanikop assert(size_ != 0); 66*09537850SAkhilesh Sanikop return elements_[begin_]; 67*09537850SAkhilesh Sanikop } 68*09537850SAkhilesh Sanikop 69*09537850SAkhilesh Sanikop // Returns a reference to the element at the back of the queue. It is an error 70*09537850SAkhilesh Sanikop // to call Back() when the queue is empty. Back()71*09537850SAkhilesh Sanikop T& Back() { 72*09537850SAkhilesh Sanikop assert(size_ != 0); 73*09537850SAkhilesh Sanikop const size_t back = ((end_ == 0) ? capacity_ : end_) - 1; 74*09537850SAkhilesh Sanikop return elements_[back]; 75*09537850SAkhilesh Sanikop } 76*09537850SAkhilesh Sanikop 77*09537850SAkhilesh Sanikop // Clears the queue. Clear()78*09537850SAkhilesh Sanikop void Clear() { 79*09537850SAkhilesh Sanikop while (!Empty()) { 80*09537850SAkhilesh Sanikop Pop(); 81*09537850SAkhilesh Sanikop } 82*09537850SAkhilesh Sanikop } 83*09537850SAkhilesh Sanikop 84*09537850SAkhilesh Sanikop // Returns true if the queue is empty. Empty()85*09537850SAkhilesh Sanikop bool Empty() const { return size_ == 0; } 86*09537850SAkhilesh Sanikop 87*09537850SAkhilesh Sanikop // Returns true if the queue is full. Full()88*09537850SAkhilesh Sanikop bool Full() const { return size_ >= capacity_; } 89*09537850SAkhilesh Sanikop 90*09537850SAkhilesh Sanikop // Returns the number of elements in the queue. Size()91*09537850SAkhilesh Sanikop size_t Size() const { return size_; } 92*09537850SAkhilesh Sanikop 93*09537850SAkhilesh Sanikop private: 94*09537850SAkhilesh Sanikop // An array of |capacity| elements. Used as a circular array. 95*09537850SAkhilesh Sanikop std::unique_ptr<T[]> elements_; 96*09537850SAkhilesh Sanikop size_t capacity_ = 0; 97*09537850SAkhilesh Sanikop // The index of the element to be removed by Pop(). 98*09537850SAkhilesh Sanikop size_t begin_ = 0; 99*09537850SAkhilesh Sanikop // The index where the new element is inserted by Push(). 100*09537850SAkhilesh Sanikop size_t end_ = 0; 101*09537850SAkhilesh Sanikop size_t size_ = 0; 102*09537850SAkhilesh Sanikop }; 103*09537850SAkhilesh Sanikop 104*09537850SAkhilesh Sanikop } // namespace libgav1 105*09537850SAkhilesh Sanikop 106*09537850SAkhilesh Sanikop #endif // LIBGAV1_SRC_UTILS_QUEUE_H_ 107