2016-05-31 22:44:49 +08:00
|
|
|
//===-- esan_circular_buffer.h ----------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// 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);
|
2016-06-04 00:27:50 +08:00
|
|
|
WasConstructed = true;
|
2016-05-31 22:44:49 +08:00
|
|
|
}
|
|
|
|
~CircularBuffer() {
|
2016-06-04 00:27:50 +08:00
|
|
|
if (WasConstructed) // Else caller will call free() explicitly.
|
|
|
|
free();
|
2016-05-31 22:44:49 +08:00
|
|
|
}
|
|
|
|
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;
|
2016-06-04 00:27:50 +08:00
|
|
|
WasConstructed = false;
|
2016-05-31 22:44:49 +08:00
|
|
|
}
|
|
|
|
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&);
|
|
|
|
|
2016-06-04 00:27:50 +08:00
|
|
|
bool WasConstructed;
|
2016-05-31 22:44:49 +08:00
|
|
|
T *Data;
|
|
|
|
uptr Capacity;
|
|
|
|
uptr StartIdx;
|
|
|
|
uptr Count;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace __esan
|