Loading...
Searching...
No Matches
CircularBuffer.H
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2022-2023 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26Class
27 Foam::CircularBuffer
28
29Description
30 A simple list of objects of type <T> that is intended to be used
31 as a circular buffer (eg, a FIFO) when the alloc/free overhead
32 associated with a linked-list approach is to be avoided.
33
34 The internal storage is addressed by independent begin/end markers.
35 - The %begin marker points to the \em front.
36 - The %end marker is a one-past the \em back.
37 .
38 This results in a variety ofr different possible buffer states:
39 -# \em empty (\em begin == \em end)
40
41 -# \em simple/linear (\em begin < \em end) has no wrapping:
42 \verbatim
43 |.|.|.|a|b|c|d|.|.|.|
44 beg ___^
45 end ___________^
46 \endverbatim
47
48 -# \em split (\em begin > \em end):
49 \verbatim
50 |f|g|h|i|.|.|.|a|b|c|d|e|
51 end _____^
52 beg ___________^
53 \endverbatim
54 .
55
56 The methods range_one(), range_two() return the internal indexing and
57 the methods array_one(), array_two() provide direct access to the
58 internal contents.
59
60 When filling the buffer, the internal storage will be resized
61 (doubling strategy) as required. When this occurs, the new list
62 will be linearized with \em begin = 0.
63
64 Simultaneously when filling, the storage buffer will be over-allocated
65 to avoid ambiguity when (\em begin == \em end), which represents an
66 \em %empty buffer and not a \em %full buffer. Eg,
67 \verbatim
68 |c|d|.|a|b|
69 end _^
70 beg ___^
71 \endverbatim
72 after appending one more, it would be incorrect to simply fill
73 the available space:
74 \verbatim
75 |c|d|e|a|b|
76 end ___^ WRONG : would represent empty!
77 beg ___^
78 \endverbatim
79 the storage is instead increased (doubled) and rebalanced before
80 the append occurs (old capacity 5, new capacity 10):
81 \verbatim
82 |a|b|c|d|e|.|.|.|.|.|
83 _^_ beg
84 end _______^
85 \endverbatim
86
87SourceFiles
88 CircularBuffer.C
89 CircularBufferI.H
90 CircularBufferIO.C
91
92\*---------------------------------------------------------------------------*/
93
94#ifndef Foam_CircularBuffer_H
95#define Foam_CircularBuffer_H
96
97#include "List.H"
98#include "SubList.H"
99
100// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
101
102namespace Foam
103{
104
105// Forward Declarations
106template<class T> class CircularBuffer;
107
108template<class T>
110
111template<class T>
113
114
115/*---------------------------------------------------------------------------*\
116 Class CircularBuffer Declaration
117\*---------------------------------------------------------------------------*/
118
119template<class T>
120class CircularBuffer
121{
122 // Private Data
123
124 //- The allocated buffer storage
125 List<T> storage_;
126
127 //- The first addressable element
128 label begin_;
129
130 //- One past last addressable element
131 label end_;
132
133
134 // Private Member Functions
135
136 //- Map the logical location to the buffer location
137 inline label toGlobal(const label i) const;
138
139 //- Length of array one
140 inline label size_one() const noexcept;
141
142 //- Length of array two
143 inline label size_two() const noexcept;
144
145 //- Reserve allocation space for at least this size.
146 // Never shrinks the allocated size, use setCapacity() for that.
147 // The 'nocopy' option will not attempt to recover old content
148 void doReserve(const bool nocopy, const label len);
149
150 //- Copy all list contents
151 template<class OtherListType>
152 inline void copyList(const OtherListType& rhs);
153
154
155public:
156
157 // STL type definitions
158
159 //- The value type the list contains
160 typedef T value_type;
161
162 //- The pointer type for non-const access to value_type items
163 typedef T* pointer;
164
165 //- The pointer type for const access to value_type items
166 typedef const T* const_pointer;
167
168 //- The type used for storing into value_type objects
169 typedef T& reference;
170
171 //- The type used for reading from constant value_type objects
172 typedef const T& const_reference;
173
174 //- The type to represent the size of a buffer
175 typedef label size_type;
176
177 //- The difference between iterator objects
178 typedef label difference_type;
180 //- Forward iterator with const access
181 class const_iterator;
182
183
184 // Constructors
185
186 //- Default construct, empty buffer without allocation
187 inline constexpr CircularBuffer() noexcept;
188
189 //- Construct an empty buffer with given reserve size
190 inline explicit CircularBuffer(const label len);
191
192 //- Copy construct
193 inline CircularBuffer(const CircularBuffer<T>& list);
195 //- Move construct
197
198 //- Construct from Istream - uses readList
199 explicit CircularBuffer(Istream& is);
200
201
202 // Member Functions
203
204 // Characteristics
205
206 //- Lower capacity limit
207 static constexpr label min_size() noexcept { return 16; }
208
209 //- Size of the underlying storage.
210 inline label capacity() const noexcept;
211
212 //- Empty or exhausted buffer
213 inline bool empty() const noexcept;
214
215 //- The current number of buffer items
216 inline label size() const noexcept;
217
218
219 // Internal Access
220
221 //- The nominal space available to fill.
222 //- Subtract 1 for the number to append before re-balancing is needed.
223 inline label space() const noexcept;
224
225 //- The addressing range covered by array_one()
226 inline labelRange range_one() const noexcept;
227
228 //- The addressing range covered by array_two()
229 inline labelRange range_two() const noexcept;
230
231 //- The contents of the first internal array
233
234 //- The contents of the second internal array
236
237 //- The contents of the first internal array
238 const SubList<T> array_one() const;
239
240 //- The contents of the second internal array
241 const SubList<T> array_two() const;
242
243
244 // Access
245
246 //- Access the first element (front). Requires !empty().
248
249 //- Access the last element (back). Requires !empty().
250 T& back();
251
252 //- Const access to the first element (front). Requires !empty().
253 const T& front() const;
254
255 //- Const access to the last element (back). Requires !empty().
256 const T& back() const;
257
258
259 // Sizing
260
261 //- Reserve allocation space for at least this size, allocating new
262 //- space if required and \em retaining old content.
263 // Never shrinks.
264 inline void reserve(const label len);
265
266 //- Reserve allocation space for at least this size, allocating new
267 //- space if required \em without retaining old content.
268 // Never shrinks.
269 inline void reserve_nocopy(const label len);
270
271 //- Clear the addressed buffer, does not change allocation
272 inline void clear() noexcept;
273
274 //- Clear the buffer and delete storage.
275 inline void clearStorage();
276
277 //- Swap content, independent of sizing parameter
278 inline void swap(CircularBuffer<T>& other);
279
280
281 // Search
282
283 //- True if the value is contained in the list.
284 inline bool contains(const T& val) const;
285
286 //- Is the value contained in the list?
287 // \param val The value to search for
288 // \param pos The first position to examine (no-op if -ve)
289 // \return true if found.
290 inline bool contains(const T& val, label pos) const;
291
292 //- Find index of the first occurrence of the value.
293 // Any occurrences before the start pos are ignored.
294 // Linear search.
295 // \return position in list or -1 if not found.
296 label find(const T& val, label pos = 0) const;
297
298
299 // Stack-like Operations
300
301 //- Copy prepend an element to the front of the buffer
302 inline void push_front(const T& val);
303
304 //- Move prepend an element to the front of the buffer
305 inline void push_front(T&& val);
306
307 //- Construct an element at the front of the buffer,
308 //- return reference to the new element
309 template<class... Args>
310 inline T& emplace_front(Args&&... args);
311
312 //- Copy append an element to the end of the buffer
313 inline void push_back(const T& val);
314
315 //- Move append an element to the end of the buffer
316 inline void push_back(T&& val);
317
318 //- Construct an element at the end of the buffer,
319 //- return reference to the new element
320 template<class... Args>
321 inline T& emplace_back(Args&&... args);
322
323 //- Shrink by moving the front of the buffer 1 or more times
324 inline void pop_front(label n = 1);
325
326 //- Shrink by moving the end of the buffer 1 or more times
327 inline void pop_back(label n = 1);
328
329 //- Copy append multiple elements the end of the buffer
330 inline void push_back(const UList<T>& list);
331
332 //- Copy append IndirectList elements the end of the buffer
333 template<class Addr>
334 inline void push_back(const IndirectListBase<T, Addr>& list);
335
336 //- Append an element if not already in the buffer.
337 // \return the change in the buffer length
338 inline label push_uniq(const T& val);
339
340
341 // Other Operations
342
343 //- Return a copy of the buffer flattened into a single List.
344 //- Use sparingly!
345 List<T> list() const;
346
347 //- Reverse the buffer order, swapping elements
348 void reverse();
349
350
351 // Member Operators
352
353 //- Non-const access to an element in the list.
354 // The index is allowed to wrap in both directions
355 inline T& operator[](const label i);
356
357 //- Const access to an element in the list
358 // The index is allowed to wrap in both directions
359 inline const T& operator[](const label i) const;
360
361 //- Copy construct
362 inline void operator=(const CircularBuffer<T>& list);
363
364 //- Move construct
365 inline void operator=(CircularBuffer<T>&& list);
366
367 //- Assign all addressed elements to the given value
368 inline void operator=(const T& val);
369
370 //- Assignment of all entries to zero
371 inline void operator=(Foam::zero);
372
373 //- Deep copy values from a list of the addressed elements
374 inline void operator=(const UList<T>& rhs);
375
376 //- Deep copy values from a list of the addressed elements
377 template<class AnyAddr>
378 inline void operator=(const IndirectListBase<T, AnyAddr>& rhs);
379
380
381 // IOstream Operators
382
383 //- Print information
384 Ostream& info(Ostream& os) const;
385
386 //- Read buffer contents from Istream.
388
389 //- Write buffer contents with line-breaks in ASCII
390 //- when length exceeds shortLen.
391 // Using '0' suppresses line-breaks entirely.
392 Ostream& writeList(Ostream& os, const label shortLen=0) const;
393
394 //- Use the readList() method to read contents from Istream.
395 friend Istream& operator>> <T>
396 (
397 Istream& is,
399 );
400
401 //- Write to Ostream
402 friend Ostream& operator<< <T>
403 (
404 Ostream& os,
405 const CircularBuffer<T>& list
406 );
407
408
409 // Iterators
410
411 //- A simple forward const iterator for a circular buffer
412 class const_iterator
413 {
414 const CircularBuffer<T>* container_;
415 label iter_;
416
417 public:
418
419 using difference_type = label;
420 using value_type = const T;
421 using pointer = const T*;
422 using reference = const T&;
423 using iterator_category = std::forward_iterator_tag;
424
425 const_iterator(const const_iterator&) = default;
426 const_iterator& operator=(const const_iterator&) = default;
427
429 (
430 const CircularBuffer<T>* buffer,
431 label i
432 )
433 :
434 container_(buffer),
435 iter_(i)
436 {}
437
438 reference operator*() const
439 {
440 return (*container_)[iter_];
441 }
442
443 const_iterator& operator++()
444 {
445 ++iter_;
446 return *this;
447 }
448
449 const_iterator operator++(int)
450 {
451 auto old(*this);
452 ++iter_;
453 return old;
454 }
455
456 bool operator==(const const_iterator& rhs) const
457 {
458 return iter_ == rhs.iter_;
459 }
460
461 bool operator!=(const const_iterator& rhs) const
462 {
463 return iter_ != rhs.iter_;
464 }
465 };
466
467
468 // Iterator (const)
469
470 //- Return a const_iterator at begin of buffer
471 inline const_iterator cbegin() const
472 {
473 return const_iterator(this, 0);
474 }
475
476 //- Return a const_iterator at end of buffer
477 inline const_iterator cend() const
478 {
479 return const_iterator(this, this->size());
480 }
481
482 //- Return a const_iterator at begin of buffer
483 inline const_iterator begin() const { return cbegin(); }
484
485 //- Return a const_iterator at end of buffer
486 inline const_iterator end() const { return cend(); }
487};
488
489
490// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
491
492//- Read buffer contents from Istream
493template<class T>
495{
496 return rhs.readList(is);
497}
498
499
500//- Write buffer contents to Ostream,
501//- as per CircularBuffer::writeList() with default length.
502template<class T>
504{
505 return rhs.writeList(os);
506}
507
508
509// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
510
511} // End namespace Foam
512
513// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
514
515#include "CircularBufferI.H"
516
517// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
518
519#ifdef NoRepository
520 #include "CircularBuffer.C"
521 #include "CircularBufferIO.C"
522#endif
523
524// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
525
526#endif
527
528// ************************************************************************* //
label n
A simple forward const iterator for a circular buffer.
std::forward_iterator_tag iterator_category
const_iterator(const CircularBuffer< T > *buffer, label i)
const_iterator(const const_iterator &)=default
bool operator!=(const const_iterator &rhs) const
bool operator==(const const_iterator &rhs) const
const_iterator & operator=(const const_iterator &)=default
A simple list of objects of type <T> that is intended to be used as a circular buffer (eg,...
label size_type
The type to represent the size of a buffer.
void pop_front(label n=1)
Shrink by moving the front of the buffer 1 or more times.
void clear() noexcept
Clear the addressed buffer, does not change allocation.
labelRange range_one() const noexcept
The addressing range covered by array_one().
T & emplace_front(Args &&... args)
Construct an element at the front of the buffer, return reference to the new element.
label difference_type
The difference between iterator objects.
void pop_back(label n=1)
Shrink by moving the end of the buffer 1 or more times.
T value_type
The value type the list contains.
constexpr CircularBuffer() noexcept
Default construct, empty buffer without allocation.
const_iterator begin() const
Return a const_iterator at begin of buffer.
void reverse()
Reverse the buffer order, swapping elements.
const_iterator cbegin() const
Return a const_iterator at begin of buffer.
T & emplace_back(Args &&... args)
Construct an element at the end of the buffer, return reference to the new element.
bool empty() const noexcept
Empty or exhausted buffer.
bool contains(const T &val) const
True if the value is contained in the list.
void reserve_nocopy(const label len)
Reserve allocation space for at least this size, allocating new space if required without retaining o...
T & back()
Access the last element (back). Requires !empty().
const T * const_pointer
The pointer type for const access to value_type items.
T * pointer
The pointer type for non-const access to value_type items.
void clearStorage()
Clear the buffer and delete storage.
Ostream & info(Ostream &os) const
Print information.
label push_uniq(const T &val)
Append an element if not already in the buffer.
label capacity() const noexcept
Size of the underlying storage.
label find(const T &val, label pos=0) const
Find index of the first occurrence of the value.
const_iterator cend() const
Return a const_iterator at end of buffer.
label size() const noexcept
The current number of buffer items.
T & reference
The type used for storing into value_type objects.
void push_back(const T &val)
Copy append an element to the end of the buffer.
T & front()
Access the first element (front). Requires !empty().
static constexpr label min_size() noexcept
Lower capacity limit.
SubList< T > array_two()
The contents of the second internal array.
List< T > list() const
Return a copy of the buffer flattened into a single List. Use sparingly!
void reserve(const label len)
Reserve allocation space for at least this size, allocating new space if required and retaining old c...
Ostream & writeList(Ostream &os, const label shortLen=0) const
Write buffer contents with line-breaks in ASCII when length exceeds shortLen.
labelRange range_two() const noexcept
The addressing range covered by array_two().
void swap(CircularBuffer< T > &other)
Swap content, independent of sizing parameter.
label space() const noexcept
The nominal space available to fill. Subtract 1 for the number to append before re-balancing is neede...
void push_front(const T &val)
Copy prepend an element to the front of the buffer.
const_iterator end() const
Return a const_iterator at end of buffer.
Istream & readList(Istream &is)
Read buffer contents from Istream.
void operator=(const CircularBuffer< T > &list)
Copy construct.
SubList< T > array_one()
The contents of the first internal array.
const T & const_reference
The type used for reading from constant value_type objects.
Base for lists with indirect addressing, templated on the list contents type and the addressing type....
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition Istream.H:60
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition Ostream.H:59
A non-owning sub-view of a List (allocated or unallocated storage).
Definition SubList.H:61
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition UList.H:89
A range or interval of labels defined by a start and a size.
Definition labelRange.H:66
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition zero.H:58
OBJstream os(runTime.globalPath()/outputName)
surface1 clear()
Namespace for OpenFOAM.
bool operator!=(const eddy &a, const eddy &b)
Definition eddy.H:297
dimensionedScalar pos(const dimensionedScalar &ds)
void reverse(UList< T > &list, const label n)
Reverse the first n elements of the list.
Definition UListI.H:539
tmp< faMatrix< Type > > operator*(const areaScalarField::Internal &, const faMatrix< Type > &)
Ostream & operator<<(Ostream &, const boundaryPatch &p)
Write boundaryPatch as dictionary entries (without surrounding braces).
tmp< faMatrix< Type > > operator==(const faMatrix< Type > &, const faMatrix< Type > &)
Istream & operator>>(Istream &, directionInfo &)
void rhs(fvMatrix< typename Expr::value_type > &m, const Expr &expression)
const direction noexcept
Definition scalarImpl.H:265
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
triangles reserve(surf.size())
Foam::argList args(argc, argv)