#ifndef QUEUE_H #define QUEUE_H #include "core/error_macros.h" #include "vector.h" template class Queue { public: void enqueue(const T &job); T dequeue(); const T &peek() const; bool is_empty() const; bool is_full() const; int size() const; int capacity() const; void ensure_capacity(const int capacity); void resize(const int s); void pack(); Queue(); Queue(int prealloc); Queue(int prealloc, int grow_by); ~Queue(); private: T* _data; int _head; int _tail; int _capacity; int _grow_size; }; template void Queue::pack() { if (_head == _tail) { _head = 0; _tail = 0; return; } if (_head == 0 && _tail == _capacity) { resize(_capacity + _grow_size); return; } int j = 0; for (int i = _head; i < _tail; ++i) { _data[j++] = _data[i]; } _head = 0; _tail = j; } template void Queue::enqueue(const T &job) { if (_tail == _capacity) { pack(); } _data[_tail++] = job; } template T Queue::dequeue() { CRASH_COND(is_empty()); return _data[_head++]; } template const T &Queue::peek() const { CRASH_COND(is_empty()); return _data[_head]; } template bool Queue::is_empty() const { return _head == _tail; } template bool Queue::is_full() const { return (_head == 0) && (_tail == _capacity); } template int Queue::size() const { return _tail - _head; } template int Queue::capacity() const { return _capacity; } template void Queue::ensure_capacity(const int capacity) { if (_capacity < capacity) { resize(capacity); } } template void Queue::resize(const int s) { if (s == 0 && _data) { delete[] _data; _data = nullptr; _capacity = s; return; } if (!_data) { _data = new T[s]; _capacity = s; return; } if (is_empty()) { delete[] _data; _data = new T[s]; _capacity = s; return; } if (!is_full()) { pack(); } T* nd = new T[s]; int to = s > _tail ? _tail : s; for (int i = 0; i < to; ++i) { nd[i] = _data[i]; } delete[] _data; _data = nd; _capacity = s; } template Queue::Queue() { _data = nullptr; _head = 0; _tail = 0; _capacity = 20; _grow_size = 10; resize(_capacity); } template Queue::Queue(int prealloc) { _data = nullptr; _head = 0; _tail = 0; _capacity = prealloc; _grow_size = 10; resize(_capacity); } template Queue::Queue(int prealloc, int grow_by) { _data = nullptr; _head = 0; _tail = 0; _capacity = prealloc; _grow_size = grow_by; resize(_capacity); } template Queue::~Queue() { if (_data) { delete[] _data; _data = nullptr; } } #endif