ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
19 июня
1525380 Топик полностью
=AlexD= (17.06.2025 14:42, просмотров: 73) ответил Dingo на Господа, может кто поделиться или порекомендовать си реализацию double buffer на произвольный тип данных? Вроде и немного писать, но это же очередное повторение велосипеда. Два массива, пока один заполняем, второй для чтения. Я свои не сподобился оформить отдельным функционалом.
DeepSeek 

Вот реализация двойной буферизации на языке 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. Реализация потокобезопасна для однопоточного использования (для многопоточного нужно добавить мьютексы)

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

Это моё личное предвзятое мнение. Любое совпадение с реальностью является случайным и непреднамеренным.