#ifndef QUEUE_H #define QUEUE_H #include "core/error_macros.h" #include "vector.h" template<class T> 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 <class T> void Queue<T>::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 <class T> void Queue<T>::enqueue(const T &job) { if (_tail == _capacity) { pack(); } _data[_tail++] = job; } template <class T> T Queue<T>::dequeue() { CRASH_COND(is_empty()); return _data[_head++]; } template <class T> const T &Queue<T>::peek() const { CRASH_COND(is_empty()); return _data[_head]; } template <class T> bool Queue<T>::is_empty() const { return _head == _tail; } template <class T> bool Queue<T>::is_full() const { return (_head == 0) && (_tail == _capacity); } template <class T> int Queue<T>::size() const { return _tail - _head; } template <class T> int Queue<T>::capacity() const { return _capacity; } template <class T> void Queue<T>::ensure_capacity(const int capacity) { if (_capacity < capacity) { resize(capacity); } } template <class T> void Queue<T>::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 <class T> Queue<T>::Queue() { _data = nullptr; _head = 0; _tail = 0; _capacity = 20; _grow_size = 10; resize(_capacity); } template <class T> Queue<T>::Queue(int prealloc) { _data = nullptr; _head = 0; _tail = 0; _capacity = prealloc; _grow_size = 10; resize(_capacity); } template <class T> Queue<T>::Queue(int prealloc, int grow_by) { _data = nullptr; _head = 0; _tail = 0; _capacity = prealloc; _grow_size = grow_by; resize(_capacity); } template <class T> Queue<T>::~Queue() { if (_data) { delete[] _data; _data = nullptr; } } #endif