10 #include <boost/thread/condition.hpp> 11 #include <boost/thread/mutex.hpp> 12 #include <boost/thread/thread.hpp> 13 #include <boost/circular_buffer.hpp> 14 #include <boost/lexical_cast.hpp> 16 #include "../Debug/debug.h" 17 #include "../jTypeTraits/jtypetraits.h" 21 template <
typename T >
28 template <
typename F >
29 friend std::ostream& operator<< (std::ostream& stream, ouroborus<F>& buffer);
31 void HeadInsert( T* to_insert, uint insert_size );
32 void TailInsert( T* to_insert, uint insert_size );
34 std::vector<T> HeadRead( uint read_size );
35 template <
typename F >
36 std::vector< F > HeadReadAndConvert( uint read_size );
37 bool CheckHead( uint read_size );
39 std::vector<T> TailRead( uint read_size );
40 template <
typename F >
41 std::vector< F > TailReadAndConvert( uint read_size );
42 bool CheckTail( uint read_size );
53 void update_counter(
int update_value );
55 boost::circular_buffer<T> internal_buffer;
56 boost::shared_mutex monitor;
58 bool overrun_flag =
false;
62 template <
typename T >
67 template <
typename T>
69 DEBUG_PRINT(
"Built new ring_buffer of size " << buffer_size );
72 template <
typename T >
73 std::ostream& operator << (std::ostream& stream, ouroborus<T>& buffer) {
75 stream <<
"Maximum buffer size: " << buffer.internal_buffer.capacity() << std::endl;
76 stream <<
"Number of elements in buffer: " << buffer.internal_buffer.size() << std::endl;
77 stream <<
"Front of buffer: " << buffer.internal_buffer.front() << std::endl;
78 stream <<
"Back of buffer: " << buffer.internal_buffer.back() << std::endl;
79 stream <<
"Buffer contents: " << std::endl;
81 for(
const auto& elem : buffer.internal_buffer ) {
82 stream << elem <<
",";
90 template <
typename T >
92 boost::shared_lock<boost::shared_mutex> lock( monitor );
96 template <
typename T >
98 boost::shared_lock<boost::shared_mutex> lock( monitor );
99 return internal_buffer.capacity();
102 template <
typename T >
104 boost::shared_lock<boost::shared_mutex> lock( monitor );
105 return internal_buffer.size();
108 template <
typename T >
110 boost::shared_lock<boost::shared_mutex> lock( monitor );
112 internal_buffer.clear();
113 overrun_flag =
false;
116 template <
typename T >
119 DEBUG_PRINT(
"Inserting " << insert_size <<
" elements into ring buffer" );
122 boost::upgrade_lock<boost::shared_mutex> lock( monitor );
124 boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock);
126 auto head = to_insert;
127 auto tail = head + insert_size;
129 if( (internal_buffer.size() + insert_size) >= internal_buffer.capacity() ) {
133 internal_buffer.insert( internal_buffer.begin(), head, tail );
137 template <
typename T >
140 DEBUG_PRINT(
"Inserting " << insert_size <<
" elements into ring buffer" );
143 boost::upgrade_lock<boost::shared_mutex> lock( monitor );
145 boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock);
147 auto head = to_insert;
148 auto tail = head + insert_size;
150 if( (internal_buffer.size() + insert_size) >= internal_buffer.capacity() ) {
154 internal_buffer.insert( internal_buffer.end(), head, tail );
158 template <
typename T >
162 boost::upgrade_lock<boost::shared_mutex> lock( monitor );
164 boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock);
166 auto first = internal_buffer.begin();
167 auto last = internal_buffer.begin() + data_size;
171 bool check_condition = (std::distance(first, last) < data_size);
173 if (check_condition) {
174 DEBUG_PRINT( __func__ <<
" Unable to read, not enough samples in ring buffer" );
176 DEBUG_PRINT( __func__ <<
" Able to read." );
179 return !check_condition;
182 template <
typename T >
186 boost::upgrade_lock<boost::shared_mutex> lock( monitor );
188 boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock);
190 auto first = internal_buffer.end() - data_size;
191 auto last = internal_buffer.end() ;
195 bool check_condition = (std::distance(first, last) < data_size);
197 if (check_condition) {
198 DEBUG_PRINT( __func__ <<
" Unable to read, not enough samples in ring buffer" );
200 DEBUG_PRINT( __func__ <<
" Able to read." );
203 return !check_condition;
206 template <
typename T >
210 boost::shared_lock<boost::shared_mutex> lock( monitor );
212 auto first = internal_buffer.end() - read_size;
213 auto last = internal_buffer.end() ;
216 bool check_condition = (std::distance(first, last) < read_size);
218 if (check_condition) {
219 DEBUG_PRINT( __func__ <<
" Unable to read, not enough samples in ring buffer" );
221 std::string err_str =
"Not enough new data in ring buffer: Have ";
222 err_str += boost::lexical_cast<std::string>( internal_buffer.size() );
223 err_str +=
" new data samples, but ";
224 err_str += boost::lexical_cast<std::string>( read_size );
225 err_str +=
" were requested.";
226 throw std::ios_base::failure(err_str);
229 DEBUG_PRINT( __func__ <<
" Able to read." );
232 auto copy_vec = std::vector< T >( first, last );
234 internal_buffer.erase ( first, last );
239 template <
typename T >
240 template <
typename F >
244 boost::shared_lock<boost::shared_mutex> lock( monitor );
246 auto first = internal_buffer.end() - read_size;
247 auto last = internal_buffer.end() ;
250 bool check_condition = (std::distance(first, last) < read_size);
252 if (check_condition) {
253 DEBUG_PRINT( __func__ <<
" Unable to read, not enough samples in ring buffer" );
255 std::string err_str =
"Not enough new data in ring buffer: Have ";
256 err_str += boost::lexical_cast<std::string>( internal_buffer.size() );
257 err_str +=
" new data samples, but ";
258 err_str += boost::lexical_cast<std::string>( read_size );
259 err_str +=
" were requested.";
260 throw std::ios_base::failure(err_str);
263 DEBUG_PRINT( __func__ <<
" Able to read." );
266 auto copy_vec = std::vector< F >( first, last );
268 internal_buffer.erase ( first, last );
273 template <
typename T >
277 boost::shared_lock<boost::shared_mutex> lock( monitor );
279 auto first = internal_buffer.begin() + 0;
280 auto last = internal_buffer.begin() + read_size;
284 bool check_condition = (std::distance(first, last) < read_size);
286 if (check_condition) {
287 DEBUG_PRINT( __func__ <<
" Unable to read, not enough samples in ring buffer" );
289 std::string err_str =
"Not enough new data in ring buffer: Have ";
290 err_str += boost::lexical_cast<std::string>( internal_buffer.size() );
291 err_str +=
" new data samples, but ";
292 err_str += boost::lexical_cast<std::string>( read_size );
293 err_str +=
" were requested.";
294 throw std::ios_base::failure(err_str);
296 DEBUG_PRINT( __func__ <<
" Able to read." );
299 auto copy_vec = std::vector< T >( first, last );
301 internal_buffer.erase ( first, last );
306 template <
typename T >
307 template <
typename F >
311 boost::shared_lock<boost::shared_mutex> lock( monitor );
313 auto first = internal_buffer.begin() + 0;
314 auto last = internal_buffer.begin() + read_size;
318 bool check_condition = (std::distance(first, last) < read_size);
320 if (check_condition) {
321 DEBUG_PRINT( __func__ <<
" Unable to read, not enough samples in ring buffer" );
323 std::string err_str =
"Not enough new data in ring buffer: Have ";
324 err_str += boost::lexical_cast<std::string>( internal_buffer.size());
325 err_str +=
" new data samples, but ";
326 err_str += boost::lexical_cast<std::string>( read_size );
327 err_str +=
" were requested.";
328 throw std::ios_base::failure(err_str);
330 DEBUG_PRINT( __func__ <<
" Able to read." );
333 auto copy_vec = std::vector< F >( first, last );
335 internal_buffer.erase ( first, last );
343 #endif // OUROBOROS_H