Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #pragma once 11 : 12 : #include "Buffer.h" 13 : 14 : namespace MooseUtils 15 : { 16 : 17 : /** 18 : * An optimized LIFO (Last In First Out) buffer. 19 : * 20 : * Begin()/end() iterators can be used in OpenMP loops 21 : * Also operator[] works sequentially between 0 and size() 22 : * 23 : * It will also automatically grow larger if capacity is reached 24 : */ 25 : template <typename T> 26 : class LIFOBuffer : public Buffer<T> 27 : { 28 : public: 29 : /** 30 : * Create an empty LIFO buffer 31 : */ 32 : LIFOBuffer(); 33 : 34 : LIFOBuffer(const std::size_t capacity); 35 : 36 : virtual void erase(const std::size_t num) override; 37 : virtual void eraseChunk(const std::size_t chunk_size) override; 38 : 39 : virtual typename Buffer<T>::iterator beginChunk(const std::size_t chunk_size) override; 40 : virtual typename Buffer<T>::const_iterator 41 : beginChunk(const std::size_t chunk_size) const override; 42 : virtual typename Buffer<T>::iterator endChunk(const std::size_t chunk_size) override; 43 : virtual typename Buffer<T>::const_iterator endChunk(const std::size_t chunk_size) const override; 44 : 45 : protected: 46 : virtual std::size_t newEnd(const std::size_t new_end) override; 47 : }; 48 : 49 : template <typename T> 50 : LIFOBuffer<T>::LIFOBuffer() : Buffer<T>() 51 : { 52 : } 53 : 54 : template <typename T> 55 1 : LIFOBuffer<T>::LIFOBuffer(const std::size_t capacity) : Buffer<T>(capacity) 56 : { 57 1 : } 58 : 59 : template <typename T> 60 : void 61 11 : LIFOBuffer<T>::erase(const std::size_t num) 62 : { 63 : mooseAssert(num <= this->size(), "Cannot erase past the last entry"); 64 : 65 11 : this->_end_pos -= num; 66 : 67 : // If there's nothing in the buffer - let's reset the positions 68 11 : if (this->_begin_pos == this->_end_pos) 69 2 : this->clear(); 70 11 : } 71 : 72 : template <typename T> 73 : void 74 5 : LIFOBuffer<T>::eraseChunk(const std::size_t chunk_size) 75 : { 76 5 : if (chunk_size > this->size()) 77 1 : this->erase(this->size()); 78 : else 79 4 : this->erase(chunk_size); 80 5 : } 81 : 82 : template <typename T> 83 : typename Buffer<T>::iterator 84 5 : LIFOBuffer<T>::beginChunk(const std::size_t chunk_size) 85 : { 86 5 : if (chunk_size > this->size()) 87 1 : return this->begin(); 88 : else 89 4 : return this->end() - chunk_size; 90 : } 91 : 92 : template <typename T> 93 : typename Buffer<T>::const_iterator 94 0 : LIFOBuffer<T>::beginChunk(const std::size_t chunk_size) const 95 : { 96 0 : if (chunk_size > this->size()) 97 0 : return this->begin(); 98 : else 99 0 : return this->end() - chunk_size; 100 : } 101 : 102 : template <typename T> 103 : typename Buffer<T>::iterator 104 5 : LIFOBuffer<T>::endChunk(const std::size_t /* chunk_size */) 105 : { 106 5 : return this->end(); 107 : } 108 : 109 : template <typename T> 110 : typename Buffer<T>::const_iterator 111 0 : LIFOBuffer<T>::endChunk(const std::size_t /* chunk_size */) const 112 : { 113 0 : return this->end(); 114 : } 115 : 116 : template <typename T> 117 : std::size_t 118 40 : LIFOBuffer<T>::newEnd(const std::size_t new_end) 119 : { 120 40 : if (new_end > this->_data.size()) 121 : { 122 3 : auto new_size = new_end - this->_begin_pos; 123 : 124 3 : this->_data.resize(std::max(new_size * 2, this->_data.size() * 2)); 125 : } 126 : 127 40 : return new_end; 128 : } 129 : 130 : }