- Принял (максимальное или заранее известное количество) данных;
- Обработка данных;
- Отправил подтверждение;
- GOTO 1
Если организовать последний сценарий с помощью "обычного" буфера, который можно представить такой структурой
struct buf {
unsigned char *data;
unsigned long lenth;
};
, то появляется некоторая негибкость или потеря производительности при чтении буфера, если мы берём за правило тот факт, что мы хотим читать произвольное количество данных: если читать самые старые данные, то после нужно смещать остаток буфера, длинной (buf.lenth - read_data_size) к его началу, освобождая место в "хвосте" для новых данных. Такая операция с памятью займёт очень много времени, которое зависит от размера имеющихся данных. Либо же мы можем читать последние данные, декрементируя счётчик размера буфера. Понятно, что далеко не всегда такой подход удовлетворяет логику процесса.unsigned char *data;
unsigned long lenth;
};
Для увеличения производительности буфера можно организовать его в кольцо. Аттрибуты такого кольцевого буфера: собственно, сам буфер, представляющий собой выделенную область памяти определённой длинны; счётчик записи; счётчик чтения.
Логику работы буфера можно описать следующими положениями:
- Счётчик чтения всегда "догоняет" счётчик записи;
- Если значения счётчиков достигло размера выделенной памяти, то они зануляются (уходят на следующий круг);
- Если счётчик записи обогнал счётчик чтения на круг, то запись должна прекратиться (возможно, теряя поступающие данные), либо счётчик чтения должен инкрементироваться вслед за записью (теряя самые старые данные).
Пример реализации процедур записи и чтения:
/* Round-robin buffer */
struct rr_buf {
unsigned char *data;
unsigned short wrPos; // счётчик записи
unsigned short rdPos; // счётчик чтения
unsigned char rounded; // счётчик записи ушёл на второй круг, а чтения - нет
unsigned char overflow; // может быть использовано, если допустима потеря данных
};
struct rr_buf buf;
unsigned short
buf_write(unsigned char *data, unsigned long size)
{
/* Bytes have been written */
unsigned short bwritten = 0;
while(bwritten < size) {
/* Not enough space */
if(g_buf.wrPos == g_buf.rdPos && g_buf.rounded)
break;
/* Writing byte by byte */
*(g_buf.data + g_buf.wrPos) = *(data + bwritten);
g_buf.wrPos++;
if(g_buf.wrPos == SC_BUF_SIZE) {
g_buf.wrPos = 0;
g_buf.rounded = 1;
}
bwritten++;
}
return bwritten;
}
unsigned short
buf_read(unsigned char *data, unsigned long size)
{
unsigned short bread = 0;
while(bread %lt size) {
/* End of data */
if(buf.wrPos == buf.rdPos && !buf.rounded)
break;
*(data + bread) = *(buf.data + buf.rdPos);
buf.rdPos++;
if(buf.rdPos == BUF_SIZE) {
buf.rdPos = 0;
buf.rounded = 0;
}
bread++;
}
return bread;
}
/* May be useful */
unsigned short
get_data_size(void)
{
unsigned short size;
if(buf.rounded)
size = BUF_SIZE - buf.rdPos + buf.wrPos;
else
size = buf.wrPos - buf.rdPos;
return size;
}
struct rr_buf {
unsigned char *data;
unsigned short wrPos; // счётчик записи
unsigned short rdPos; // счётчик чтения
unsigned char rounded; // счётчик записи ушёл на второй круг, а чтения - нет
unsigned char overflow; // может быть использовано, если допустима потеря данных
};
struct rr_buf buf;
unsigned short
buf_write(unsigned char *data, unsigned long size)
{
/* Bytes have been written */
unsigned short bwritten = 0;
while(bwritten < size) {
/* Not enough space */
if(g_buf.wrPos == g_buf.rdPos && g_buf.rounded)
break;
/* Writing byte by byte */
*(g_buf.data + g_buf.wrPos) = *(data + bwritten);
g_buf.wrPos++;
if(g_buf.wrPos == SC_BUF_SIZE) {
g_buf.wrPos = 0;
g_buf.rounded = 1;
}
bwritten++;
}
return bwritten;
}
unsigned short
buf_read(unsigned char *data, unsigned long size)
{
unsigned short bread = 0;
while(bread %lt size) {
/* End of data */
if(buf.wrPos == buf.rdPos && !buf.rounded)
break;
*(data + bread) = *(buf.data + buf.rdPos);
buf.rdPos++;
if(buf.rdPos == BUF_SIZE) {
buf.rdPos = 0;
buf.rounded = 0;
}
bread++;
}
return bread;
}
/* May be useful */
unsigned short
get_data_size(void)
{
unsigned short size;
if(buf.rounded)
size = BUF_SIZE - buf.rdPos + buf.wrPos;
else
size = buf.wrPos - buf.rdPos;
return size;
}
Комментариев нет:
Отправить комментарий