Класс FIFO-буффера (C++)

Рейтинг пользователей: / 4
ХудшийЛучший 
Статьи - Программирование

first-in-first-outВ статье описывается класс Fifo-буфера, позволяющий хранить в нем объекты произвольного размера.

При разработке приложений, требующих обработки потока данных при ограниченных ресурсах, нередко возникает необходимость временного хранения данных, ожидающих обработки.

Несмотря на то, что использование для временного хранения данных в таких приложения FIFO буфера является стандартным решением, простого и удобного в использовании инструмента для работы с FIFO буфером мне найти не удалось, в результате был создан собственный класс.

Класс создавался, прежде всего, под проекты на микроконтроллерах, в которых использование функций динамического распределения памяти, как правило, нерационально.

Напомню, что принцип работы FIFO буфера заключается в том, что объекты помещаются и извлекаются из буфера по принципу «Первым вошел, первым вышел», т.е. чем раньше объект добавлен в буфер, тем быстрее он будет из него извлечен.

Листинг класса приведен ниже

#ifndef FIFO_H_
#define FIFO_H_
template <unsigned int Tsize>
class CFifoBuffer
{
private:
   // -------- Данные -------- //
   // Буфер хранения данных
   unsigned char Data[Tsize];
   // Переменная хранения адреса выборки
   unsigned int Addr;
   // Переменная хранения задействованного объема памяти
   unsigned int Size;
public:
   // Метод добавления данных в буфер
   unsigned char Add(unsigned char *pSavaData, unsigned char SaveSize)
   {
      unsigned int AddrTemp;
      if(((Tsize - Size) < (SaveSize + 1)) || (SaveSize == 0))  return 0;
      AddrTemp = Addr + Size;
      if(AddrTemp >= Tsize) {AddrTemp -= Tsize;  }
      Data[AddrTemp] = SaveSize;
      AddrTemp++;
      for(unsigned int i = 0; i < SaveSize; i++, AddrTemp++)
      {
         if(AddrTemp >= Tsize) {AddrTemp -= Tsize;}
         Data[AddrTemp] = pSavaData[i];
      }
      Size += SaveSize + 1;
      return 1;
   }
   // Метод извлечения данных из буфера
   unsigned int Cut(unsigned char *pData)
   {
      unsigned char SizeTemp;
      unsigned int AddrTemp = Addr;
      if(Size == 0) return 0;
      SizeTemp = Data[Addr] - 1;
      if(SizeTemp == 0) return 0;
      AddrTemp++;
      for(unsigned int i = 0; i <= SizeTemp; i++, AddrTemp++)
      {
         if(AddrTemp >= Tsize) {AddrTemp -= Tsize;  }
         pData[i] = Data[AddrTemp];
      }
      SizeTemp += 2;
      Size -= SizeTemp;
      Addr = AddrTemp;
      if(Addr >= Tsize) {Addr -= Tsize;  }
      return SizeTemp - 1;
   }
   // Конструктор
   CFifoBuffer(void)
   {
      Addr = 0;
      Size = 0;
   }
};
#endif

Поскольку класс является шаблонным, то тело методов приведено непосредственно в h-файле.

Краткое описание данных класса приведено непосредственно в листинге и дополнительных комментариев не требует.

Для добавления и извлечения данных из буфера используются методы Add и Cut соответственно.

Метод Add добавляет SaveSize байт буфера pSaveData в буфер Data, метод возвращает результат добавления данных в буфер:

0 – если данные не были добавлены в буфер;

1 –если данные в буфер добавлены.

Метод Cut извлекает из буфера Data объект и помещает его в буфер pData, метод возвращает размер извлеченного объекта в байтах.

При объявлении объектов класса необходимо указать размер буфера в байта.

Пример объявления объекта

CFifoBuffer<200> ExBufRx;

где 200 - размер буфера в байтах

Не смотря на то, что методы работают с массивами типа unsigned char, класс позволяет хранить объекты любого типа при этом для необходимо заведомо знать тип сохраняемых объектов, а если тип объекта неизвестен, то вводить дополнительный байт-идентификатор.

Пример добавления и извлечения различных типов данных в буфер приведен ниже. Чтобы не создавать несколько примеров для каждого типа данных, я в одном примере показал добавление объектов различных типов, чего в реальных проектах делать не рекомендую.

#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include "fifo.h"

// Объявляем структуру для демонстрации возможнослей класса
struct STemp
{
    int AnyData;
    char str[8];
};

int main(void)
{
    // Объявляем объект класса с буфером 20 байт
    CFifoBuffer <20> MyBuf;

    int iData = 1234567;
    float fData = 34.5;
    STemp MyStruct;

    MyStruct.AnyData = 98765;
    strcpy(MyStruct.str, "Test");

    // Добавляем объекты в FIFO буфер
    if(MyBuf.Add((unsigned char *)&iData, sizeof(iData)))
    {
       printf("Object iData add FIFO\n\r");
    }
    else
    {
       printf("Object iData don`t add FIFO\n\r");
    }

    if(MyBuf.Add((unsigned char *)&fData, sizeof(fData)))
    {
       printf("Object fData add FIFO\n\r");
    }
    else
    {
       printf("Object fData don`t add FIFO\n\r");
    }

    // Объект MyStruct не будет добавлен т.к. буфер переполнен
    if(MyBuf.Add((unsigned char *)&MyStruct, sizeof(MyStruct)))
    {
       printf("Object MyStruct add FIFO\n\r");
    }
    else
    {
       printf("Object MyStruct don`t add FIFO\n\r");
    }

    printf("\n\r\n\r");

    // Извлекаем объект iData из буфера
    int iTemp = 0;
    if(MyBuf.Cut((unsigned char *)&iTemp))
    {
       printf("Object iData = %d\n\r", iTemp);
    }
    else
    {
       printf("Object iData don`t cut\n\t");
    }

    // Добавляем объект MyStruct
    if(MyBuf.Add((unsigned char *)&MyStruct, sizeof(MyStruct)))
    {
       printf("Object MyStruct add FIFO\n\r");
    }
    else
    {
       printf("Object MyStruct don`t add FIFO\n\r");
    }

    // Извлекаем объекты из буфера
    float fTemp = 0;
    if(MyBuf.Cut((unsigned char *)&fTemp))
    {
       printf("Object fData = %f\n\r", fTemp);
    }
    else
    {
       printf("Object fData don`t cut\n\t");
    }

    STemp MyStructTemp;
    if(MyBuf.Cut((unsigned char *)&MyStructTemp))
    {
       printf("Object MyStruct.AnyData = %d\n\r", MyStructTemp.AnyData);
       printf("Object MyStruct.str = %s\n\r", MyStructTemp.str);
    }
    else
    {
       printf("Object fData don`t cut\n\r");
    }

    return 0;
}

Результат выполнения примера приведен на рисунке.

Результат работы программыВ завершении обращаю внимание, что при объявлении в одном и том же проекте объектов класса с различным объемом буфера в памяти программ компилятором будет создано соответствующее количество копий методов т.е. для работы с буфером размера N1 будут использоваться одни методы, для работы с буфером размера N2 другие.

 Обсудить на форуме (0 комментариев).

Добавить комментарий

Правила комментирования

Запрещается вводить оскорбительные тексты, использовать нецензурные выражения, публиковать экстремистские призывы, давать ссылки на сайты, не имеющие отношения к теме обсуждения. Все сообщения, нарушающие данные требования, будут удалены без уведомлений, а их авторы - заблокированы.
Незарегистрированные посетители не могут вводить ссылки, BB-коды и т.п., зарегистрированные - могут. Подробности о возможностях, доступных зарегистрированным посетителям, см. в разделе Помощь.


Защитный код
Обновить



Темы форума
Комментарии
Статистика
Просмотров:
mod_vvisit_counterСегодня3200
mod_vvisit_counterВчера4220
mod_vvisit_counterНа этой неделе3200
mod_vvisit_counterНа прошлой неделе51381
mod_vvisit_counterВ этом месяце183392
mod_vvisit_counterЗа все время11545613

Ваш IP: 54.162.136.26
 , 
29 Май. 2017