// ----------------------------------------------------------------------------------------
//
//  common/util/cbuffer.h
//    
//  Bob Cook Development, Robotics Library
//  http://www.bobcookdev.com/rl/
//    
//  This file provides a circular buffer template.
//
//  Copyright (C) 2007 Bob Cook
//
//      This program is free software; you can redistribute it and/or modify it
//      under the terms of the GNU General Public License as published by the
//      Free Software Foundation; either version 2 of the License, or (at your
//      option) any later version.
//    
//      This program is distributed in the hope that it will be useful, but 
//      WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
//      or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
//      for more details.
//    
//      You should have received a copy of the GNU General Public License along
//      with this program; if not, write to the Free Software Foundation, Inc., 
//      51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
//
// ----------------------------------------------------------------------------------------


#if !defined( BCDRL_COMMON_UTIL_CBUFFER_H )
#define BCDRL_COMMON_UTIL_CBUFFER_H


#include <stdint.h>


// ----------------------------------------------------------------------------------------
//  cbuffer
//
//      A circular buffer that can be templatized to specific types as required.
//

template< typename T_ELEM_TYPE, typename T_SIZE_TYPE, int T_SIZE >
class cbuffer
{
    public:

        // --------------------------------------------------------------------------------
        //  Initialize an empty buffer.
        //
        cbuffer();

        // --------------------------------------------------------------------------------
        //  Test if the buffer is full.
        //
        bool is_full() const;

        // --------------------------------------------------------------------------------
        //  Test if the buffer is empty.
        //
        bool is_empty() const;

        // --------------------------------------------------------------------------------
        //  Add an element to the buffer; if the buffer is already full the new element
        //  will be ignored.
        //
        void push( const T_ELEM_TYPE& element );

        // --------------------------------------------------------------------------------
        //  Spin-wait for available space then add an element to the buffer. Do not use
        //  this function from an interrupt handler or other non-interruptible code.
        //
        void wait_and_push( const T_ELEM_TYPE& element );

        // --------------------------------------------------------------------------------
        //  Remove an element from the buffer; returns the most recent element if the
        //  buffer is empty.
        //
        T_ELEM_TYPE pop();

        // --------------------------------------------------------------------------------
        //  Spin-wait while the buffer is empty; remove the first available element from 
        //  the buffer. Do not use this function from an interrupt handler or other non-
        //  interruptible code.
        //
        T_ELEM_TYPE wait_and_pop();

        // --------------------------------------------------------------------------------
        //  Erase the entire buffer.
        //
        void clear();

private:

        T_ELEM_TYPE m_buffer[ T_SIZE ];
        volatile T_SIZE_TYPE m_head;
        volatile T_SIZE_TYPE m_tail;
};


// ----------------------------------------------------------------------------------------

template< int T_SIZE >
class cbytebuffer
    : public cbuffer< uint8_t, uint8_t, T_SIZE >
{
};


// ----------------------------------------------------------------------------------------
//  Include the template functions.
//

#include "packages/common/util/cbuffer.inl"


#endif // #if !defined( BCDRL_COMMON_UTIL_CBUFFER_H )
// ----------------------------------------------------------------------------------------
//  end of cbuffer.h
// ----------------------------------------------------------------------------------------

