xref: /aosp_15_r20/external/compiler-rt/lib/esan/esan_circular_buffer.h (revision 7c3d14c8b49c529e04be81a3ce6f5cc23712e4c6)
1*7c3d14c8STreehugger Robot //===-- esan_circular_buffer.h ----------------------------------*- C++ -*-===//
2*7c3d14c8STreehugger Robot //
3*7c3d14c8STreehugger Robot //                     The LLVM Compiler Infrastructure
4*7c3d14c8STreehugger Robot //
5*7c3d14c8STreehugger Robot // This file is distributed under the University of Illinois Open Source
6*7c3d14c8STreehugger Robot // License. See LICENSE.TXT for details.
7*7c3d14c8STreehugger Robot //
8*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
9*7c3d14c8STreehugger Robot //
10*7c3d14c8STreehugger Robot // This file is a part of EfficiencySanitizer, a family of performance tuners.
11*7c3d14c8STreehugger Robot //
12*7c3d14c8STreehugger Robot // Circular buffer data structure.
13*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
14*7c3d14c8STreehugger Robot 
15*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_common.h"
16*7c3d14c8STreehugger Robot 
17*7c3d14c8STreehugger Robot namespace __esan {
18*7c3d14c8STreehugger Robot 
19*7c3d14c8STreehugger Robot // A circular buffer for POD data whose memory is allocated using mmap.
20*7c3d14c8STreehugger Robot // There are two usage models: one is to use initialize/free (for global
21*7c3d14c8STreehugger Robot // instances) and the other is to use placement new with the
22*7c3d14c8STreehugger Robot // constructor and to call the destructor or free (they are equivalent).
23*7c3d14c8STreehugger Robot template<typename T>
24*7c3d14c8STreehugger Robot class CircularBuffer {
25*7c3d14c8STreehugger Robot  public:
26*7c3d14c8STreehugger Robot   // To support global instances we cannot initialize any field in the
27*7c3d14c8STreehugger Robot   // default constructor.
CircularBuffer()28*7c3d14c8STreehugger Robot   explicit CircularBuffer() {}
CircularBuffer(uptr BufferCapacity)29*7c3d14c8STreehugger Robot   CircularBuffer(uptr BufferCapacity) {
30*7c3d14c8STreehugger Robot     initialize(BufferCapacity);
31*7c3d14c8STreehugger Robot     WasConstructed = true;
32*7c3d14c8STreehugger Robot   }
~CircularBuffer()33*7c3d14c8STreehugger Robot   ~CircularBuffer() {
34*7c3d14c8STreehugger Robot     if (WasConstructed) // Else caller will call free() explicitly.
35*7c3d14c8STreehugger Robot       free();
36*7c3d14c8STreehugger Robot   }
initialize(uptr BufferCapacity)37*7c3d14c8STreehugger Robot   void initialize(uptr BufferCapacity) {
38*7c3d14c8STreehugger Robot     Capacity = BufferCapacity;
39*7c3d14c8STreehugger Robot     // MmapOrDie rounds up to the page size for us.
40*7c3d14c8STreehugger Robot     Data = (T *)MmapOrDie(Capacity * sizeof(T), "CircularBuffer");
41*7c3d14c8STreehugger Robot     StartIdx = 0;
42*7c3d14c8STreehugger Robot     Count = 0;
43*7c3d14c8STreehugger Robot     WasConstructed = false;
44*7c3d14c8STreehugger Robot   }
free()45*7c3d14c8STreehugger Robot   void free() {
46*7c3d14c8STreehugger Robot     UnmapOrDie(Data, Capacity * sizeof(T));
47*7c3d14c8STreehugger Robot   }
48*7c3d14c8STreehugger Robot   T &operator[](uptr Idx) {
49*7c3d14c8STreehugger Robot     CHECK_LT(Idx, Count);
50*7c3d14c8STreehugger Robot     uptr ArrayIdx = (StartIdx + Idx) % Capacity;
51*7c3d14c8STreehugger Robot     return Data[ArrayIdx];
52*7c3d14c8STreehugger Robot   }
53*7c3d14c8STreehugger Robot   const T &operator[](uptr Idx) const {
54*7c3d14c8STreehugger Robot     CHECK_LT(Idx, Count);
55*7c3d14c8STreehugger Robot     uptr ArrayIdx = (StartIdx + Idx) % Capacity;
56*7c3d14c8STreehugger Robot     return Data[ArrayIdx];
57*7c3d14c8STreehugger Robot   }
push_back(const T & Item)58*7c3d14c8STreehugger Robot   void push_back(const T &Item) {
59*7c3d14c8STreehugger Robot     CHECK_GT(Capacity, 0);
60*7c3d14c8STreehugger Robot     uptr ArrayIdx = (StartIdx + Count) % Capacity;
61*7c3d14c8STreehugger Robot     Data[ArrayIdx] = Item;
62*7c3d14c8STreehugger Robot     if (Count < Capacity)
63*7c3d14c8STreehugger Robot       ++Count;
64*7c3d14c8STreehugger Robot     else
65*7c3d14c8STreehugger Robot       StartIdx = (StartIdx + 1) % Capacity;
66*7c3d14c8STreehugger Robot   }
back()67*7c3d14c8STreehugger Robot   T &back() {
68*7c3d14c8STreehugger Robot     CHECK_GT(Count, 0);
69*7c3d14c8STreehugger Robot     uptr ArrayIdx = (StartIdx + Count - 1) % Capacity;
70*7c3d14c8STreehugger Robot     return Data[ArrayIdx];
71*7c3d14c8STreehugger Robot   }
pop_back()72*7c3d14c8STreehugger Robot   void pop_back() {
73*7c3d14c8STreehugger Robot     CHECK_GT(Count, 0);
74*7c3d14c8STreehugger Robot     --Count;
75*7c3d14c8STreehugger Robot   }
size()76*7c3d14c8STreehugger Robot   uptr size() const {
77*7c3d14c8STreehugger Robot     return Count;
78*7c3d14c8STreehugger Robot   }
clear()79*7c3d14c8STreehugger Robot   void clear() {
80*7c3d14c8STreehugger Robot     StartIdx = 0;
81*7c3d14c8STreehugger Robot     Count = 0;
82*7c3d14c8STreehugger Robot   }
empty()83*7c3d14c8STreehugger Robot   bool empty() const { return size() == 0; }
84*7c3d14c8STreehugger Robot 
85*7c3d14c8STreehugger Robot  private:
86*7c3d14c8STreehugger Robot   CircularBuffer(const CircularBuffer&);
87*7c3d14c8STreehugger Robot   void operator=(const CircularBuffer&);
88*7c3d14c8STreehugger Robot 
89*7c3d14c8STreehugger Robot   bool WasConstructed;
90*7c3d14c8STreehugger Robot   T *Data;
91*7c3d14c8STreehugger Robot   uptr Capacity;
92*7c3d14c8STreehugger Robot   uptr StartIdx;
93*7c3d14c8STreehugger Robot   uptr Count;
94*7c3d14c8STreehugger Robot };
95*7c3d14c8STreehugger Robot 
96*7c3d14c8STreehugger Robot } // namespace __esan
97