gctf2023/pwn/flipper/dist/common/include/util/RingBuffer.h

80 lines
1.4 KiB
C
Raw Normal View History

2023-11-24 18:11:34 +00:00
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#ifdef __cplusplus
}
#endif
#include "new.h"
#include "ArchThreads.h"
#include "assert.h"
template<class T>
class RingBuffer
{
public:
RingBuffer ( uint32 size=128 );
~RingBuffer();
bool get ( T &c );
void put ( T c );
void clear();
private:
size_t buffer_size_;
T *buffer_;
size_t write_pos_;
size_t read_pos_;
};
template <class T>
RingBuffer<T>::RingBuffer ( uint32 size )
{
assert ( size>1 );
buffer_size_=size;
buffer_=new T[buffer_size_];
write_pos_=1;
read_pos_=0;
}
template <class T>
RingBuffer<T>::~RingBuffer()
{
delete[] buffer_;
}
template <class T>
void RingBuffer<T>::put ( T c )
{
size_t old_write_pos=write_pos_;
if ( old_write_pos == read_pos_ )
return;
buffer_[old_write_pos]=c;
ArchThreads::testSetLock ( write_pos_, ( old_write_pos + 1 ) % buffer_size_ );
}
template <class T>
void RingBuffer<T>::clear()
{
ArchThreads::testSetLock ( write_pos_,1 );
// assumed that there is only one reader who can't have called clear and get at the same time.
// here get would return garbage.
ArchThreads::testSetLock ( read_pos_,0 );
}
template <class T>
bool RingBuffer<T>::get ( T &c )
{
uint32 new_read_pos = ( read_pos_ + 1 ) % buffer_size_;
if ( write_pos_ == new_read_pos ) //nothing new to read
return false;
c = buffer_[new_read_pos];
ArchThreads::testSetLock ( read_pos_,new_read_pos );
return true;
}