| //===-- 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 |