Допустим, есть структура очереди. В неё можно читать и из неё писать. Объём памяти, выделенный под очередь, фиксированный (задаётся при создании). Очередь в себе хранит указатели на первый и последний элемент (при этом если мы доходим до конца массива во время чтения или записи, то переходим к его началу). Всё хорошо работает, однако возможна ситуация, когда в очереди кончится свободное место. В этом случае надо дождаться, пока оно появиться. Аналогично мы можем хотеть считать из очереди N байт, а если их не хватает, то дождаться их появления.
Busy loop это не круто. Однако у меня есть специальный примитив синхронизации - EventSource. Он поддерживает две основные операции - ожидание сигнала и отправка сигнала. Если поток ждёт сигнал, он не потребляет ресурсы. Отправка сигнала пробуждает все ждущие потоки.
На Linux реализуется этот примитив через pthread_condvar (параметр mutex не используем, передавая свежий mutex, который уничтожаем сразу же после вызова). Под моей личной RTOS реализуется нативно.
Теперь поступаем просто - после каждой записи или чтения посылаем соответственно сигнал о записи или о чтении. Если записали/прочитали не всё, что хотели, то ждём противоположный сигнал (если хотим записать, ждём пока кто-то прочитает, если хотим прочитать, то ждём, пока кто-нибудь запишет).
Возникает логичная проблема. А что если мы отправим сигнал о, скажем, записи. В этот момент нас нагло прервёт проснувшийся поток, который ждал, пока появятся данные в очереди (и мы его разбудили), вытащит из очереди все данные, пошлёт сигнал чтения, а затем снова уснёт от их недостатка. И только теперь к нам возвращается управление и мы начинаем ждать событие чтения. А оно не придёт! Потому что тот кто хотел уже всё прочитал и ждёт, пока нового события записи, которое мы отправили ранее и больше не отправим, пока не запишем ещё.
И что с этим делать? Надо как-то научиться принимать сигналы из прошлого. Скажем, заведём флаг и будем сбрасывать его в false в начале каждой записи/чтения, а после окончания записи (либо если кончилось место/данные в очереди) устанавливаем в true флаг противоположного действия помимо отправки сигнала. В ожидание переходим лишь если флаг остался в false. Но это не поможет - нас могут прервать внутри самой функции ожидания, до того как она собственно начнёт ждать. И она точно также пропустит сигнал.
Конечно, в своей RTOS я могу что-то нахимичить (сделать проверку флага и переход в ожидание, если его нет, атомарным), но не в pthread же.
Как вообще такое надо делать?
Моя кривая реализация очереди, если что - https://github.com/KivApple/controllerFramework/blob/master/libraries/platfor...