Commit | Line | Data |
---|---|---|
d1d120e1 JM |
1 | // |
2 | // Simple fixed size ring buffer. | |
3 | // Manage objects by value. | |
4 | // Thread safe for single Producer and single Consumer. | |
5 | // By Dennis Lang http://home.comcast.net/~lang.dennis/code/ring/ring.html | |
6 | // Slightly modified for naming | |
7 | ||
8 | #pragma once | |
9 | ||
10 | template <class T, size_t RingSize> | |
11 | class TSRingBuffer | |
12 | { | |
13 | public: | |
14 | TSRingBuffer() | |
15 | : m_size(RingSize), m_buffer(new T[RingSize]), m_rIndex(0), m_wIndex(0) | |
16 | { } | |
17 | ||
18 | ~TSRingBuffer() | |
19 | { | |
20 | delete [] m_buffer; | |
21 | }; | |
22 | ||
23 | size_t next(size_t n) const | |
24 | { | |
25 | return (n + 1) % m_size; | |
26 | } | |
27 | ||
28 | bool empty() const | |
29 | { | |
30 | return (m_rIndex == m_wIndex); | |
31 | } | |
32 | ||
33 | bool full() const | |
34 | { | |
35 | return (next(m_wIndex) == m_rIndex); | |
36 | } | |
37 | ||
38 | bool put(const T &value) | |
39 | { | |
40 | if (full()) | |
41 | return false; | |
42 | m_buffer[m_wIndex] = value; | |
43 | m_wIndex = next(m_wIndex); | |
44 | return true; | |
45 | } | |
46 | ||
47 | bool get(T &value) | |
48 | { | |
49 | if (empty()) | |
50 | return false; | |
51 | value = m_buffer[m_rIndex]; | |
52 | m_rIndex = next(m_rIndex); | |
53 | return true; | |
54 | } | |
55 | ||
56 | private: | |
57 | size_t m_size; | |
58 | T *m_buffer; | |
59 | ||
60 | // volatile is only used to keep compiler from placing values in registers. | |
61 | // volatile does NOT make the index thread safe. | |
62 | volatile size_t m_rIndex; | |
63 | volatile size_t m_wIndex; | |
64 | }; |