Вот реализация двойной буферизации на языке C:
```c
#include <stdbool.h>
#include <string.h>
#define BUFFER_SIZE 1024
typedef struct {
unsigned char buffers[2][BUFFER_SIZE];
int write_index; // Индекс буфера для записи (0 или 1)
int read_index; // Индекс буфера для чтения (0 или 1)
size_t write_pos; // Текущая позиция записи в активном буфере
size_t read_pos; // Текущая позиция чтения в активном буфере
bool write_ready[2]; // Флаги готовности буферов для чтения
} DoubleBuffer;
void db_init(DoubleBuffer *db) {
memset(db, 0, sizeof(DoubleBuffer));
}
// Запись данных в буфер
size_t db_put(DoubleBuffer *db, const unsigned char *data, size_t len) {
size_t written = 0;
while (written < len) {
// Количество доступного места в текущем буфере для записи
size_t available = BUFFER_SIZE - db->write_pos;
if (available == 0) {
// Текущий буфер заполнен, переключаемся на другой
db->write_ready[db->write_index] = true;
db->write_index = 1 - db->write_index;
db->write_pos = 0;
available = BUFFER_SIZE;
}
// Количество байт для записи в этом цикле
size_t to_write = (len - written) < available ? (len - written) : available;
memcpy(db->buffers[db->write_index] + db->write_pos, data + written, to_write);
db->write_pos += to_write;
written += to_write;
}
return written;
}
// Чтение данных из буфера
size_t db_get(DoubleBuffer *db, unsigned char *data, size_t len) {
size_t read = 0;
while (read < len) {
// Если текущий буфер для чтения пуст и второй готов - переключаемся
if (db->read_pos >= BUFFER_SIZE ||
(!db->write_ready[db->read_index] && db->write_ready[1 - db->read_index])) {
db->read_index = 1 - db->read_index;
db->read_pos = 0;
db->write_ready[db->read_index] = false;
}
// Если нет данных для чтения - выходим
if (!db->write_ready[db->read_index] && db->read_pos >= db->write_pos && db->read_index == db->write_index) {
break;
}
// Определяем сколько можно прочитать
size_t available;
if (db->read_index == db->write_index) {
available = db->write_pos - db->read_pos;
} else {
available = BUFFER_SIZE - db->read_pos;
}
if (available == 0) break;
size_t to_read = (len - read) < available ? (len - read) : available;
memcpy(data + read, db->buffers[db->read_index] + db->read_pos, to_read);
db->read_pos += to_read;
read += to_read;
}
return read;
}
```
### Пример использования:
```c
int main() {
DoubleBuffer db;
db_init(&db);
// Пример записи
unsigned char data_to_write[1500];
// ... заполняем data_to_write ...
db_put(&db, data_to_write, 1500);
// Пример чтения
unsigned char data_to_read[1000];
size_t bytes_read = db_get(&db, data_to_read, 1000);
return 0;
}
```
### Особенности реализации:
1. Используются два буфера фиксированного размера (BUFFER_SIZE)
2. Функция `db_put` автоматически переключается на второй буфер при заполнении первого
3. Функция `db_get` автоматически переключается на другой буфер, когда текущий прочитан полностью
4. Учитываются граничные случаи, когда данные записываются и читаются одновременно
5. Реализация потокобезопасна для однопоточного использования (для многопоточного нужно добавить мьютексы)
При необходимости можно модифицировать размер буфера или добавить механизмы синхронизации для многопоточного использования.