1 /** 2 Copyright: Copyright (c) 2013-2014 Andrey Penechko. 3 License: a$(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 7 module emulator.utils.ringbuffer; 8 9 @safe nothrow: 10 11 class RingBufferFullException : Exception 12 { 13 this(string msg, string file = __FILE__, size_t line = __LINE__) 14 { 15 super(msg, file, line); 16 } 17 } 18 19 enum OnBufferFull 20 { 21 overwrite, 22 throwException 23 } 24 25 struct RingBuffer(E, size_t bufSize, OnBufferFull onBufferFull = OnBufferFull.overwrite) 26 { 27 E[bufSize] buffer; 28 size_t frontPos; 29 size_t backPos; 30 size_t length; 31 32 @property E front() 33 { 34 return buffer[frontPos]; 35 } 36 37 @property E back() 38 { 39 return buffer[backPos]; 40 } 41 42 @property bool isFull() 43 { 44 return length >= bufSize; 45 } 46 47 @property bool empty() 48 { 49 return length == 0; 50 } 51 52 void pushBack(E element) 53 { 54 if (isFull) 55 { 56 static if (onBufferFull == OnBufferFull.overwrite) 57 { 58 backPos = (backPos + 1) % bufSize; 59 frontPos = (frontPos + 1) % frontPos; 60 61 buffer[backPos] = element; 62 63 return; 64 } 65 else 66 { 67 throw new RingBufferFullException("Ring buffer is full"); 68 } 69 } 70 71 buffer[backPos] = element; 72 backPos = (backPos + 1) % bufSize; 73 ++length; 74 } 75 76 /// Dequeue item from queue. 77 /// 78 /// Size must be checked 79 E popBack() 80 in 81 { 82 assert(length > 0); 83 } 84 body 85 { 86 --length; 87 auto temp = backPos; 88 backPos = (backPos - 1) % bufSize; 89 return buffer[temp]; 90 } 91 92 /// Dequeue item from queue. 93 /// 94 /// Size must be checked 95 E popFront() 96 in 97 { 98 assert(length > 0); 99 } 100 body 101 { 102 --length; 103 auto temp = frontPos; 104 frontPos = (frontPos + 1) % bufSize; 105 return buffer[temp]; 106 } 107 108 void pushFront(E element) 109 { 110 frontPos = (frontPos - 1) % bufSize; 111 buffer[frontPos] = element; 112 ++length; 113 } 114 115 void clear() nothrow 116 { 117 frontPos = 0; 118 backPos = 0; 119 length = 0; 120 } 121 }