triple-buf.cpp (1764B)
1 #include <array> 2 #include <atomic> 3 #include <iostream> 4 5 enum states 6 { 7 wro, 8 wrn, 9 rwo, 10 rwn, 11 12 wor, 13 wnr, 14 row, 15 rnw, 16 17 owr, 18 nwr, 19 orw, 20 nrw, 21 }; 22 23 struct state_table 24 { 25 enum states push_next, pull_next; 26 unsigned char in, out; 27 }; 28 29 constexpr struct state_table table[] = 30 { 31 [wro] = {nrw, wro, 0, 1}, 32 [wrn] = {nrw, wor, 0, 1}, 33 [rwo] = {rnw, rwo, 1, 0}, 34 [rwn] = {rnw, owr, 1, 0}, 35 [wor] = {nwr, wor, 0, 2}, 36 [wnr] = {nwr, wro, 0, 2}, 37 [row] = {rwn, row, 2, 0}, 38 [rnw] = {rwn, orw, 2, 0}, 39 [owr] = {wnr, owr, 1, 2}, 40 [nwr] = {wnr, rwo, 1, 2}, 41 [orw] = {wrn, orw, 2, 1}, 42 [nrw] = {wrn, row, 2, 1}, 43 }; 44 45 template <typename T> 46 struct triple_buffer 47 { 48 std::array<T, 3> bufs; 49 std::atomic<enum states> state; 50 51 T& get_write() 52 { 53 return bufs[table[state].in]; 54 } 55 56 T& get_read() 57 { 58 return bufs[table[state].out]; 59 } 60 61 void push(void) 62 { 63 enum states desired, expected = state; 64 do 65 { 66 desired = table[expected].push_next; 67 68 } while (not state.compare_exchange_strong(expected, desired, std::memory_order::seq_cst, std::memory_order::seq_cst)); 69 } 70 71 bool pull(void) 72 { 73 enum states desired, expected = state; 74 do 75 { 76 desired = table[expected].pull_next; 77 78 if (desired == expected) 79 return false; 80 81 } while (not state.compare_exchange_strong(expected, desired, std::memory_order::seq_cst, std::memory_order::seq_cst)); 82 83 return true; 84 } 85 }; 86 87 88 int main(void) 89 { 90 triple_buffer<int> b; 91 92 b.get_write() = 5; 93 b.push(); 94 95 b.pull(); 96 std::cout << b.get_read() << '\n'; 97 b.pull(); 98 std::cout << b.get_read() << '\n'; 99 100 b.get_write() = 6; 101 b.push(); 102 103 b.get_write() = 7; 104 b.push(); 105 106 std::cout << b.get_read() << '\n'; 107 b.pull(); 108 std::cout << b.get_read() << '\n'; 109 110 b.get_write() = 8; 111 b.push(); 112 113 b.pull(); 114 std::cout << b.get_read() << '\n'; 115 116 return 0; 117 }