Я создаю программу, которая будет получать сообщения с удаленного компьютера и должна записывать сообщения в файл на диске. Трудность, с которой я сталкиваюсь, заключается в том, что целью этой программы является проверка производительности библиотеки, которая принимает сообщения, и, следовательно, я должен убедиться, что запись сообщений на диск не влияет на производительность библиотеки. , Библиотека доставляет сообщения в программу через функцию обратного вызова. Еще одна трудность заключается в том, что решение должно быть независимым от платформы.
Какие варианты у меня есть?
Я думал о следующем:
boost:asio
записать в файл, но кажется (см. этот документация), что асинхронная запись в файл находится в специфической для Windows части этой библиотеки, поэтому ее нельзя использовать.boost::interprocess
создать очередь сообщений, но эта документация указывает, что есть 3 метода, в которых сообщения могут быть отправлены, и все методы требуют, чтобы программа блокировала (неявно или нет), если очередь сообщений заполнена, что я не могу рисковать.std::deque<MESSAGES>
нажать на deque из функции обратного вызова и выдать сообщения во время записи в файл (в отдельном потоке), но контейнеры STL не гарантируется потокобезопасность. Я мог бы заблокировать нажатие и удаление очереди, но мы говорим о 47 микросекундах между последовательными сообщениями, поэтому я хотел бы вообще избежать блокировок.У кого-нибудь есть еще идеи о возможных решениях?
Контейнеры STL могут не быть потокобезопасными, но я никогда не сталкивался с тем, который нельзя использовать в разное время в разных потоках. Передача права собственности другому потоку кажется безопасной.
Я использовал следующее пару раз, так что я знаю, что это работает:
В ветке получателя:
На потребительском потоке (пишущий диск):
Теперь, в зависимости от вашей проблемы, вам может понадобиться способ блокировки. Например, в одной из моих программ, если длина очереди достигает 100 000 элементов, производящий поток просто начинает 1 секунду спать и много жаловаться. Это одна из тех вещей, которые не должны происходить, но происходят, поэтому вы должны рассмотреть это. Безо всяких ограничений он будет просто использовать всю память на машине, а затем аварийно завершать работу, быть убитым OOM или просто остановится в шторме подкачки.
boost :: thread не зависит от платформы, поэтому вы должны иметь возможность использовать этот поток для создания записей блокировки. Чтобы избежать необходимости блокировать контейнер каждый раз, когда сообщение помещается в основной поток, вы можете использовать модификацию метода двойной буферизации, создавая вложенные контейнеры, такие как:
std::deque<std::deque<MESSAGES> >
После этого блокируйте деку верхнего уровня, только когда блок, полный сообщений, готов к добавлению. Пишущий поток, в свою очередь, блокировал бы только деку верхнего уровня, чтобы вытолкнуть деку, полную сообщений, которые должны быть написаны.