#ifndef itc_multibuffer_H_
#define itc_multibuffer_H_


//This class is used as ITC (Inter-thread communication) between threads
//with different priority, when the HP could starvate the LP. In this case,
//a simple double-buffer is not enought, a triple-buffer is required
//
//Note that this work only with ONE PRODUCER
//

class itc_multibuffer_base
{
public:
    typedef struct {
        bool produced;
    } mb_t;

public:
  itc_multibuffer_base(mb_t* b0, mb_t* b1, mb_t* b23);

  mb_t* pop_front();

  mb_t* get_back();
  void push_back();

  unsigned int not_consumed() const;
  unsigned int not_produced() const;

  unsigned int consumed() const;
  unsigned int produced() const;

  itc_multibuffer_base::mb_t* data_ready();

private:
  class implementation_t;
  implementation_t& impl;

  void operator=(const itc_multibuffer_base&);
  itc_multibuffer_base(const itc_multibuffer_base&);
};

template<class T_> class itc_multibuffer: public itc_multibuffer_base
{
public:
  typedef T_ data_t;

  typedef struct {
      bool produced;
      data_t data;
  } type_t;

  itc_multibuffer():
    itc_multibuffer_base(
          (itc_multibuffer_base::mb_t*)&(b[0]),
          (itc_multibuffer_base::mb_t*)&(b[1]),
          (itc_multibuffer_base::mb_t*)&(b[2]))
  {
  }

  type_t* data_ready() { return reinterpret_cast<type_t*>(itc_multibuffer_base::data_ready());}

  type_t* pop_front() { return reinterpret_cast<type_t*>(itc_multibuffer_base::pop_front()); }
  type_t* back() { return reinterpret_cast<type_t*>(get_back()); }

  type_t b[3];
};


class itc_multibuffer_register
{
public:
    itc_multibuffer_register(const char* const name, itc_multibuffer_base&);

    static itc_multibuffer_register* root();

    itc_multibuffer_register* next();

    itc_multibuffer_base* mb();
    const char* name();

private:
    const char* const m_name;
    itc_multibuffer_base* const m_mb;

    volatile itc_multibuffer_register* m_next;
};



#endif /*itc_multibuffer_H_*/
