lsnes rr2-β24
[lsnes.git] / src / library / triplebuffer.cpp
blob858aa40b027ba8ab8942f80644785bd194c2cb85
1 #include "triplebuffer.hpp"
2 #include <functional>
3 #include <iostream>
5 namespace triplebuffer
7 logic::logic() throw()
9 last_complete = 0;
10 current_read = 0;
11 current_write = 0;
12 count_read = 0;
13 count_write = 0;
16 unsigned logic::get_read() throw()
18 threads::alock h(lock);
19 if(count_read > 0) {
20 //We already are reading => The same as previously.
21 count_read++;
22 return current_read;
23 } else {
24 //We are beginning a new read => Pick last_complete.
25 count_read++;
26 current_read = last_complete;
27 return last_complete;
31 void logic::put_read() throw(std::logic_error)
33 threads::alock h(lock);
34 if(!count_read) throw std::logic_error("Internal error: put_read() with 0 counter");
35 count_read--;
38 unsigned logic::get_write() throw()
40 const unsigned magic = 0x010219;
41 threads::alock h(lock);
42 if(count_write > 0) {
43 //We already are writing => The same as previously.
44 count_write++;
45 return current_write;
46 } else {
47 //We are beginning a new write => Pick one that isn't last_complete nor current_read.
48 count_write++;
49 unsigned tmp = ((last_complete << 2) | current_read) << 1;
50 current_write = (magic >> tmp) & 3;
51 return current_write;
55 void logic::put_write() throw(std::logic_error)
57 threads::alock h(lock);
58 if(!count_write) throw std::logic_error("Internal error: put_write() with 0 counter");
59 count_write--;
60 //If we reached 0 counter, mark buffer as complete.
61 if(!count_write)
62 last_complete = current_write;
65 void logic::read_last_write_synchronous(std::function<void(unsigned)> fn) throw()
67 threads::alock h(lock);
68 fn(last_complete);