multithreading example

Dependencies:   FastAnalogIn

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);
}