Асинхронная поточно-безопасная регистрация в C ++ - PullRequest
16 голосов
/ 28 мая 2010

Я ищу способ сделать асинхронную и поточно-ориентированную регистрацию в моем проекте C ++, если это возможно, в один файл. В настоящее время я использую cerr и clog для этой задачи, но, поскольку они являются синхронными, выполнение вскоре приостанавливается каждый раз, когда что-то регистрируется. Это относительно графическое приложение, поэтому такие вещи довольно раздражающие.

Новый регистратор должен использовать асинхронный ввод-вывод, чтобы избавиться от этих пауз. Потокобезопасность также была бы желательна, так как я собираюсь вскоре добавить базовую многопоточность.

Я рассматривал подход «один файл на поток», но казалось, что управление журналами станет кошмаром. Есть предложения?

Ответы [ 5 ]

19 голосов
/ 26 ноября 2011

Я заметил это 1 год + старая тема. Может быть, интересующий меня асинхронный регистратор может быть интересен.

http://www.codeproject.com/KB/library/g2log.aspx

G2log использует защищенную очередь сообщений для пересылки записей журнала фоновому работнику, к которому обращается медленный диск.

Я пробовал использовать очередь без блокировки, которая увеличила среднее время вызова LOG, но сократила время наихудшего случая, однако сейчас я использую защищенную очередь, поскольку она кроссплатформенная. Он протестирован на Windows / Visual Studio 2010 и Ubuntu 11.10 / gcc4.6.

Он выпущен как общественное достояние, поэтому вы можете делать с ним все, что хотите, без каких-либо условий.

4 голосов
/ 28 мая 2010

Это ОЧЕНЬ возможно и практично. Откуда мне знать? Я написал именно это на моей последней работе. К сожалению (для нас), они теперь владеют кодом. :-) К сожалению, они даже не используют его.

Я намерен написать версию с открытым исходным кодом в ближайшем будущем. Между тем, я могу дать вам несколько советов.

  1. Манипуляторы ввода / вывода на самом деле являются просто именами функций. Вы можете реализовать их для своего собственного класса регистрации, чтобы ваш регистратор был совместим с cout / cin.
  2. Ваши функции-манипуляторы могут маркировать операции и сохранять их в очереди.
  3. В этой очереди может быть заблокирован поток, ожидающий прохождения фрагментов журнала. Затем он обрабатывает строковые операции и создает фактический журнал.

Это по своей сути совместимо с потоками, поскольку вы используете очередь. Тем не менее, вы все равно хотели бы установить некоторую мьютекс-подобную защиту для записи в очередь так, чтобы данный журнал << "stuff" << "more stuff"; Тип операции остается строковым. </p>

Веселись!

1 голос
/ 28 мая 2010

Рассматривали ли вы использование библиотеки журналов.

Есть несколько доступных, я обнаружил Pantheios недавно, и это действительно кажется невероятным.

Это скорее интерфейсный регистратор, вы можете настроить, какая система используется. Например, он может взаимодействовать с ACE или log4cxx и кажется очень простым в использовании и настройке. Основным преимуществом является то, что в нем используются безопасные операторы, что всегда здорово.

Если вы просто хотите использовать библиотеку журналов barebone:

  • ACE
  • log4c *
  • Boost.Log

Выберите любой:)

Следует отметить, что в C ++ можно реализовать очереди без блокировки и что они отлично подходят для ведения журнала.

1 голос
/ 28 мая 2010

Я думаю, что правильный подход - это не один файл на поток, а один поток на файл. Если какой-либо один файл (или ресурс в целом) в вашей системе когда-либо доступен только одному потоку, поточно-ориентированное программирование становится намного проще.

Так почему бы не сделать Logger выделенным потоком (или несколькими потоками, по одному на файл, если вы регистрируете разные вещи в разных файлах), а во всех других потоках запись в журнал поместит сообщение в очередь ввода в соответствующий поток Logger, который получит к нему после завершения написания предыдущего сообщения. Все, что требуется, - это мьютекс, чтобы защитить очередь от добавления события, пока Logger читает событие, и condvar для Logger, чтобы ждать, когда его очередь пуста.

0 голосов
/ 29 сентября 2017

У меня была такая же проблема, и я считаю, что нашел идеальное решение. Представляю вам библиотеку с одним заголовком, называемую loguru: https://github.com/emilk/loguru

Это простой в использовании, переносимый, конфигурируемый, основанный на макросах и по умолчанию ничего не #include (для этого приятного, приятного времени компиляции).

...