llvm-project/compiler-rt/lib/esan/esan_circular_buffer.h

96 lines
2.6 KiB
C++

//===-- esan_circular_buffer.h ----------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file is a part of EfficiencySanitizer, a family of performance tuners.
//
// Circular buffer data structure.
//===----------------------------------------------------------------------===//
#include "sanitizer_common/sanitizer_common.h"
namespace __esan {
// A circular buffer for POD data whose memory is allocated using mmap.
// There are two usage models: one is to use initialize/free (for global
// instances) and the other is to use placement new with the
// constructor and to call the destructor or free (they are equivalent).
template<typename T>
class CircularBuffer {
public:
// To support global instances we cannot initialize any field in the
// default constructor.
explicit CircularBuffer() {}
CircularBuffer(uptr BufferCapacity) {
initialize(BufferCapacity);
WasConstructed = true;
}
~CircularBuffer() {
if (WasConstructed) // Else caller will call free() explicitly.
free();
}
void initialize(uptr BufferCapacity) {
Capacity = BufferCapacity;
// MmapOrDie rounds up to the page size for us.
Data = (T *)MmapOrDie(Capacity * sizeof(T), "CircularBuffer");
StartIdx = 0;
Count = 0;
WasConstructed = false;
}
void free() {
UnmapOrDie(Data, Capacity * sizeof(T));
}
T &operator[](uptr Idx) {
CHECK_LT(Idx, Count);
uptr ArrayIdx = (StartIdx + Idx) % Capacity;
return Data[ArrayIdx];
}
const T &operator[](uptr Idx) const {
CHECK_LT(Idx, Count);
uptr ArrayIdx = (StartIdx + Idx) % Capacity;
return Data[ArrayIdx];
}
void push_back(const T &Item) {
CHECK_GT(Capacity, 0);
uptr ArrayIdx = (StartIdx + Count) % Capacity;
Data[ArrayIdx] = Item;
if (Count < Capacity)
++Count;
else
StartIdx = (StartIdx + 1) % Capacity;
}
T &back() {
CHECK_GT(Count, 0);
uptr ArrayIdx = (StartIdx + Count - 1) % Capacity;
return Data[ArrayIdx];
}
void pop_back() {
CHECK_GT(Count, 0);
--Count;
}
uptr size() const {
return Count;
}
void clear() {
StartIdx = 0;
Count = 0;
}
bool empty() const { return size() == 0; }
private:
CircularBuffer(const CircularBuffer&);
void operator=(const CircularBuffer&);
bool WasConstructed;
T *Data;
uptr Capacity;
uptr StartIdx;
uptr Count;
};
} // namespace __esan