You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
96 lines
2.6 KiB
96 lines
2.6 KiB
//===-- 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); |
|
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
|
|
|