When redrawing screen, read the last written frame
[lsnes.git] / include / library / triplebuffer.hpp
blobe431d63d935d81f20fd91bc52afe4b0aab2740ff
1 #ifndef _library_triplebuffer__hpp__included__
2 #define _library_triplebuffer__hpp__included__
4 #include <stdexcept>
5 #include "threads.hpp"
7 namespace triplebuffer
9 /**
10 * Triple-buffering logic.
12 class logic
14 public:
15 /**
16 * Create a new triple buffer.
18 logic() throw();
19 /**
20 * Get read pointer and increment read count by 1.
22 * Return value: Read pointer (0-2).
24 * Note: If read count is zero, last complete buffer is returned. Otherwise the same buffer as last call is returned.
26 unsigned get_read() throw();
27 /**
28 * Put read pointer and decrement read count by 1.
30 * Throws std::logic_error: If read count is 0.
32 void put_read() throw(std::logic_error);
33 /**
34 * Get write pointer and increment write count by 1.
36 * Return value: Write pointer (0-2).
38 * Note: If write count is nonzero before call, the returned buffer is the same as last time.
40 unsigned get_write() throw();
41 /**
42 * Put write pointer and decrement write count by 1. If write count hits 0, the buffer is marked as last complete
43 * buffer.
45 * Throws std::logic_error: If write count is 0.
47 void put_write() throw(std::logic_error);
48 /**
49 * Call specified function synchronously for last written buffer.
51 * The buffer number is passed to specified function.
53 void read_last_write_synchronous(std::function<void(unsigned)> fn) throw();
54 private:
55 threads::lock lock;
56 unsigned last_complete; //Number of last completed buffer
57 unsigned current_read; //Number of current read buffer (only valid if count_read > 0).
58 unsigned current_write; //Number of current write buffer (only valid if count_write > 0).
59 unsigned count_read; //Number of readers.
60 unsigned count_write; //Number of writers.
63 /**
64 * Triple buffer with objects.
66 template<typename T>
67 class triplebuffer
69 public:
70 /**
71 * Create a new triple buffer.
73 * Parameter A: Object #1.
74 * Parameter B: Object #2.
75 * Parameter C: Object #3.
77 triplebuffer(T& A, T& B, T& C) throw()
79 objs[0] = &A;
80 objs[1] = &B;
81 objs[2] = &C;
83 /**
84 * Get read pointer and increment read count by 1.
86 * Return value: Read pointer.
88 * Note: If read count is zero, last complete buffer is returned. Otherwise the same buffer as last call is returned.
90 T& get_read() throw() { return *objs[l.get_read()]; }
91 /**
92 * Put read pointer and decrement read count by 1.
94 * Throws std::logic_error: If read count is 0.
96 void put_read() throw(std::logic_error) { l.put_read(); }
97 /**
98 * Get write pointer and increment write count by 1.
100 * Return value: Write pointer.
102 * Note: If write count is nonzero before call, the returned buffer is the same as last time.
104 T& get_write() throw() { return *objs[l.get_write()]; }
106 * Put write pointer and decrement write count by 1. If write count hits 0, the buffer is marked as last complete
107 * buffer.
109 * Throws std::logic_error: If write count is 0.
111 void put_write() throw(std::logic_error) { l.put_write(); }
113 * Call specified function synchronously for last written buffer.
115 * The buffer itself is passed to the function.
117 void read_last_write_synchronous(std::function<void(T&)> fn) throw()
119 l.read_last_write_synchronous([this,fn](unsigned x){ fn(*objs[x]); });
121 private:
122 T* objs[3];
123 logic l;
127 #endif