+1. Проблемы с детектированием наезда, на необработанные данные,
обгона указателя чтения, можно решить, если использовать не
указатели, а индексы -- тогда освободятся старшие биты, в которых
можно хранить счётчик. Ну или если есть 64-битные атомики. А если
потеря данных не допустима, то увы, нужен семафор и условная
переменная. Кстати при работе с аудио интересен кольцевой буфер с тремя указателями:
В основном коде:
1) запись проигрываемых данных;
2) чтение оцифрованных (с микрофона) данных;
И в прерываниях:
3) указатель данных для записи в ЦАП и он же для чтения из АЦП.
Каждый из указателей не имеет права обгонять следующий, как и в обычном кольцевом буфере.
Кстати можно сделать, странно, что в библитечных функциях такого нет, кольцевой буфер способный хранить объекты переменного размера _непрерывно_ (т.е. к ним, пока они хранятся, можно обращаться как к объектам), и сохраняющий остальные свойства. Причём очень удобно на C++ получается: не нужно ломать голову над адресной арифметикой, а нужно переопределить арифметические операторы и итераторы и представить, что работаешь с "бесконечной лентой".
Если в кольцевой буфер пишется предсмертный лог, то чтоб вывести его, условно, одной функцией printf (и не натыкаться на конец с заворотом на начало) можно содержимое "провернуть" через std::rotate так, что начало текста будет в начале буфера. Для голого C см. алгоритм в приложенном файле ("block swap algorithm"):
s02b.pdf
Ссылки по теме:
https://en.wikipedia.org/wiki/Circular_buffer