When redrawing screen, read the last written frame
[lsnes.git] / src / library / triplebuffer.cpp
blob6444596d91e973b83aa81df4b82db1f047b50bb3
1 #include "triplebuffer.hpp"
2 #include <iostream>
4 namespace triplebuffer
6 logic::logic() throw()
8 last_complete = 0;
9 current_read = 0;
10 current_write = 0;
11 count_read = 0;
12 count_write = 0;
15 unsigned logic::get_read() throw()
17 threads::alock h(lock);
18 if(count_read > 0) {
19 //We already are reading => The same as previously.
20 count_read++;
21 return current_read;
22 } else {
23 //We are beginning a new read => Pick last_complete.
24 count_read++;
25 current_read = last_complete;
26 return last_complete;
30 void logic::put_read() throw(std::logic_error)
32 threads::alock h(lock);
33 if(!count_read) throw std::logic_error("Internal error: put_read() with 0 counter");
34 count_read--;
37 unsigned logic::get_write() throw()
39 const unsigned magic = 0x010219;
40 threads::alock h(lock);
41 if(count_write > 0) {
42 //We already are writing => The same as previously.
43 count_write++;
44 return current_write;
45 } else {
46 //We are beginning a new write => Pick one that isn't last_complete nor current_read.
47 count_write++;
48 unsigned tmp = ((last_complete << 2) | current_read) << 1;
49 current_write = (magic >> tmp) & 3;
50 return current_write;
54 void logic::put_write() throw(std::logic_error)
56 threads::alock h(lock);
57 if(!count_write) throw std::logic_error("Internal error: put_write() with 0 counter");
58 count_write--;
59 //If we reached 0 counter, mark buffer as complete.
60 if(!count_write)
61 last_complete = current_write;
64 void logic::read_last_write_synchronous(std::function<void(unsigned)> fn) throw()
66 threads::alock h(lock);
67 fn(last_complete);