summaryrefslogtreecommitdiff
path: root/src/ringbuffer.h
blob: 6a4eecfde7ba2f4178522252da6baf322d1c2e3e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#ifndef BU_RING_BUFFER_H
#define BU_RING_BUFFER_H

#include <memory>
#include "bu/exceptionbase.h"

namespace Bu
{
	/**
	 *@ingroup Containers
	 */
	template<typename value, typename valuealloc=std::allocator<value> >
	class RingBuffer
	{
	public:
		RingBuffer( int nCapacity ) :
			nCapacity( nCapacity ),
			nStart( -1 ),
			nEnd( -2 )
		{
			aData = va.allocate( nCapacity );
		}

		virtual ~RingBuffer()
		{
			for( int j = nStart; j < nEnd; j=(j+1%nCapacity) )
			{
				va.destroy( &aData[j] );
			}
			va.deallocate( aData, nCapacity );
		}

		int getCapacity()
		{
			return nCapacity;
		}

		bool isFilled()
		{
			return (nStart == nEnd);
		}

		bool isEmpty()
		{
			return (nStart == -1);
		}

		void enqueue( const value &v )
		{
			if( nStart == -1 )
			{
				nStart = 0;
				nEnd = 1;
				va.construct( &aData[0], v );
			}
			else if( nStart == nEnd )
			{
				throw ExceptionBase("Hey, it's full!");
			}
			else
			{
				va.construct( &aData[nEnd], v );
				nEnd = (nEnd+1)%nCapacity;
			}
		}

		value dequeue()
		{
			if( nStart == -1 )
			{
				throw ExceptionBase("No data");
			}
			else
			{
				value &v = aData[nStart];
				va.destroy( &aData[nStart] );
				nStart = (nStart+1)%nCapacity;
				if( nStart == nEnd )
				{
					nStart = -1;
					nEnd = -2;
				}
				return v;
			}
		}

		value &operator[]( int nIndex )
		{
			return aData[(nIndex+nStart)%nCapacity];
		}

	private:
		int nCapacity;
		value *aData;
		valuealloc va;
		int nStart, nEnd;
	};
}

#endif