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 }