112 lines
2.7 KiB
C++
112 lines
2.7 KiB
C++
#ifndef _library_triplebuffer__hpp__included__
|
|
#define _library_triplebuffer__hpp__included__
|
|
|
|
#include <stdexcept>
|
|
#include "threads.hpp"
|
|
|
|
namespace triplebuffer
|
|
{
|
|
/**
|
|
* Triple-buffering logic.
|
|
*/
|
|
class logic
|
|
{
|
|
public:
|
|
/**
|
|
* Create a new triple buffer.
|
|
*/
|
|
logic() throw();
|
|
/**
|
|
* Get read pointer and increment read count by 1.
|
|
*
|
|
* Return value: Read pointer (0-2).
|
|
*
|
|
* Note: If read count is zero, last complete buffer is returned. Otherwise the same buffer as last call is returned.
|
|
*/
|
|
unsigned get_read() throw();
|
|
/**
|
|
* Put read pointer and decrement read count by 1.
|
|
*
|
|
* Throws std::logic_error: If read count is 0.
|
|
*/
|
|
void put_read() throw(std::logic_error);
|
|
/**
|
|
* Get write pointer and increment write count by 1.
|
|
*
|
|
* Return value: Write pointer (0-2).
|
|
*
|
|
* Note: If write count is nonzero before call, the returned buffer is the same as last time.
|
|
*/
|
|
unsigned get_write() throw();
|
|
/**
|
|
* Put write pointer and decrement write count by 1. If write count hits 0, the buffer is marked as last complete
|
|
* buffer.
|
|
*
|
|
* Throws std::logic_error: If write count is 0.
|
|
*/
|
|
void put_write() throw(std::logic_error);
|
|
private:
|
|
threads::lock lock;
|
|
unsigned last_complete; //Number of last completed buffer
|
|
unsigned current_read; //Number of current read buffer (only valid if count_read > 0).
|
|
unsigned current_write; //Number of current write buffer (only valid if count_write > 0).
|
|
unsigned count_read; //Number of readers.
|
|
unsigned count_write; //Number of writers.
|
|
};
|
|
|
|
/**
|
|
* Triple buffer with objects.
|
|
*/
|
|
template<typename T>
|
|
class triplebuffer
|
|
{
|
|
public:
|
|
/**
|
|
* Create a new triple buffer.
|
|
*
|
|
* Parameter A: Object #1.
|
|
* Parameter B: Object #2.
|
|
* Parameter C: Object #3.
|
|
*/
|
|
triplebuffer(T& A, T& B, T& C) throw()
|
|
{
|
|
objs[0] = &A;
|
|
objs[1] = &B;
|
|
objs[2] = &C;
|
|
}
|
|
/**
|
|
* Get read pointer and increment read count by 1.
|
|
*
|
|
* Return value: Read pointer.
|
|
*
|
|
* Note: If read count is zero, last complete buffer is returned. Otherwise the same buffer as last call is returned.
|
|
*/
|
|
T& get_read() throw() { return *objs[l.get_read()]; }
|
|
/**
|
|
* Put read pointer and decrement read count by 1.
|
|
*
|
|
* Throws std::logic_error: If read count is 0.
|
|
*/
|
|
void put_read() throw(std::logic_error) { l.put_read(); }
|
|
/**
|
|
* Get write pointer and increment write count by 1.
|
|
*
|
|
* Return value: Write pointer.
|
|
*
|
|
* Note: If write count is nonzero before call, the returned buffer is the same as last time.
|
|
*/
|
|
T& get_write() throw() { return *objs[l.get_write()]; }
|
|
/**
|
|
* Put write pointer and decrement write count by 1. If write count hits 0, the buffer is marked as last complete
|
|
* buffer.
|
|
*
|
|
* Throws std::logic_error: If write count is 0.
|
|
*/
|
|
void put_write() throw(std::logic_error) { l.put_write(); }
|
|
private:
|
|
T* objs[3];
|
|
logic l;
|
|
};
|
|
}
|
|
|
|
#endif
|