Charles Andre
/
multithread
multithreading example
circ_buff.hpp
- Committer:
- candre97
- Date:
- 2019-12-03
- Revision:
- 113:233a2fac1911
- Parent:
- 109:1d95a4596fb5
File content as of revision 113:233a2fac1911:
#pragma once #include <cstddef> #include <stdio.h> #include <string> #include <cstring> #define DEFAULT_BUF_SIZE 512 #define DEFAULT_AE_THRES 100 #define DEFAULT_AF_THRES 412 template <class T> class CircularBuff{ private: int buffer_size; T* buffer; int read_index; int write_index; int window; int ae_thres; int af_thres; public: CircularBuff(); CircularBuff(int buffsize); CircularBuff(int buffsize, int window_size); CircularBuff(int buffsize, int ae_threshold, int af_threshold); ~CircularBuff(); bool is_full(); bool is_empty(); bool push(T input); bool push_buff(uint8_t* input_buf, int buf_size); bool window_possible(); T* pop(); int size(); int capacity(); void print(); void clear(); void set_AE_thres(int thres); T* read_window(); int get_AE_thres(); bool almost_empty(); void set_AF_thres(int thres); int get_AF_thres(); bool almost_full(); }; template <class T> CircularBuff<T>::CircularBuff(){ buffer_size = DEFAULT_BUF_SIZE+1; ae_thres = DEFAULT_AE_THRES; af_thres = DEFAULT_AF_THRES; buffer = new T[buffer_size]; read_index = 0; write_index = 0; } template <class T> CircularBuff<T>::CircularBuff(int buffsize){ buffer_size = buffsize+1; ae_thres = buffer_size/5; af_thres = buffer_size*4/5; buffer = new T[buffer_size]; read_index = 0; write_index = 0; } template <class T> CircularBuff<T>::CircularBuff(int buffsize, int window_size){ buffer_size = buffsize+1; window = window_size; buffer = new T[buffer_size]; read_index = 0; write_index = 0; } template <class T> CircularBuff<T>::CircularBuff(int buffsize, int ae_threshold, int af_threshold){ buffer_size = buffsize+1; ae_thres = ae_threshold; af_thres = af_threshold; buffer = new T[buffer_size]; read_index = 0; write_index = 0; } template <class T> CircularBuff<T>::~CircularBuff(){ delete [] buffer; buffer = NULL; } template <class T> bool CircularBuff<T>::is_full(){ if (size() == (buffer_size - 1)){ return true; } else{ return false; } } template <class T> bool CircularBuff<T>::is_empty(){ if (size() == 0){ return true; } else{ return false; } } //false if failed, true if success template <class T> bool CircularBuff<T>::push(T input){ if (!is_full()){ buffer[write_index] = input; write_index = (write_index + 1) % buffer_size; return true; } else{ return false; } } //false if failed, true if success //TODO: needs to be optimized template <class T> bool CircularBuff<T>::push_buff(uint8_t* input_buf, int input_buf_size){ int casted_input_buf_size = input_buf_size/sizeof(T); if (((size() + casted_input_buf_size) < capacity()) && ((input_buf_size % sizeof(T)) == 0)){ T* casted_input_buf = (T*) input_buf; // printf("Buffer contents: [\n"); // for(int i = 0; i < casted_input_buf_size; i++){ // //printf("%s,", std::to_string(buffer[i]).c_str()); // printf("%08x,", casted_input_buf[i]); // } // printf("\b\n]\n"); int pre_wrap_size = 0; int post_wrap_size = 0; if(write_index + casted_input_buf_size > buffer_size){ pre_wrap_size = buffer_size - write_index; post_wrap_size = casted_input_buf_size - pre_wrap_size; } else{ pre_wrap_size = casted_input_buf_size; } std::memmove(buffer + write_index, casted_input_buf, pre_wrap_size * sizeof(T)); std::memmove(buffer, casted_input_buf + pre_wrap_size, post_wrap_size * sizeof(T)); write_index = (write_index + casted_input_buf_size) % buffer_size; return true; } else{ if (input_buf_size % sizeof(T) != 0){ printf("Buffer cannot be casted to CircularBuff's data type; make sure bytes are alined\n"); } else{ printf("Input buffer too large\n"); } return false; } } //false if failed, true if success template <class T> bool CircularBuff<T>::window_possible(){ if (!is_full()){ if (read_index < write_index){ if ((write_index-1) >= read_index + window){ return true; } else{ return false; } } else if(write_index == 0){ if (buffer_size-read_index >= window){ return true; } else{ return false; } } else{ if((write_index - 1 + (buffer_size-read_index)) >= window){ return true; } else{ return false; } } return true; } else{ return false; } } //false if failed, true if success template <class T> T* CircularBuff<T>::pop(){ T* retval; if (!is_empty()){ retval = buffer + read_index; read_index = (read_index + 1) % buffer_size; return retval; } else{ return NULL; } } template <class T> int CircularBuff<T>::size(){ return (size_t) ((write_index - read_index + buffer_size) % buffer_size); } template <class T> int CircularBuff<T>::capacity(){ return (size_t) buffer_size-1; } template<class T> void CircularBuff<T>::print(){ printf("Buffer contents: [\n"); for(int i = 0; i < buffer_size; i++){ printf("%s,", std::to_string(buffer[i]).c_str()); //printf("%08x,", buffer[i]); } printf("\b\n]\n"); printf("Read index: %d \t Write index: %d \t Size: %d\n", read_index, write_index, size()); } template<class T> void CircularBuff<T>::clear(){ for(int i = 0; i < buffer_size; i++){ buffer[i] = NULL; } read_index = 0; write_index = 0; } template<class T> void CircularBuff<T>::set_AE_thres(int thres){ ae_thres = thres; } template<class T> int CircularBuff<T>::get_AE_thres(){ return ae_thres; } template<class T> bool CircularBuff<T>::almost_empty(){ return (size() < ae_thres); } template<class T> void CircularBuff<T>::set_AF_thres(int thres){ af_thres = thres; } template<class T> T* CircularBuff<T>::read_window(){ if(window_possible()){ T* temp = buffer + read_index; read_index += window; return temp; } } template<class T> int CircularBuff<T>::get_AF_thres(){ return af_thres; } template<class T> bool CircularBuff<T>::almost_full(){ return (size() > af_thres); }