[uquote="COKPOWEHEU",url="/forum/viewtopic.php?p=4102288#p4102288"]Если не равняется, то вместо наложения маски будет сравнение и вычитание/сложение, вот и все.[/uquote]
На STM32 у меня так:
Спойлер
Код: Выделить всё
uint32_t size() const
{
if constexpr (pot)
{
return (TI&)tail - (TI&)head;
}
else
{
int32_t sz = (TI&)tail - (TI&)head;
return (sz < 0) ? sz + Capacity + 1 : sz;
}
}
private:
static constexpr bool pot = std::has_single_bit(Capacity);
using TI = std::conditional_t<ThreadSafe, volatile uint32_t, uint32_t>;
T buf[Capacity + !pot];
uint32_t head, tail;
COKPOWEHEU писал(а):Пока что я вижу только явный недостаток с тем, что к полю размера нужен доступ и при записи, и при чтении. Но вы говорите, что такие реализации есть. Чем именно они настолько хороши, что перевешивают этот недостаток?
Мы о разных вещах говорим, ты пытаешься доказать превосходство одного из подходов, с чем я и не спорю, т.к., еще раз повторю, у меня самого размер отдельно не хранится, но есть и другие подходы где в переменную пишется из основного кода и прерывания, может они менее эффективные, зато накосячить тоже сложнее, пиши как хочешь, просто прерывания запрещай. Взять хоть
либы для ардуино, там есть парочка RingBuf/RingBuffer, в обоих хранится размер, в одной используется ATOMIC_BLOCK, в другой - noInterrupts().
COKPOWEHEU писал(а):Ну так вариант с размером эту проблему не решает.
Вариант с размером предполагает отключение прерываний которое решает практически все проблемы, в том числе и вышеописанную.