forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			97 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			97 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- 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
 |