#c #logging
#c #ведение журнала
Вопрос:
Я пытаюсь реализовать сценарий ведения журнала, в котором для разных компонентов в проекте есть несколько регистраторов. Все эти регистраторы пытаются выполнить запись в файл. Существует ли какая-либо библиотека для этого или какой-либо способ синхронизации активности в C (как в Java).
Также используется один дескриптор.
Комментарии:
1. параллельная очередь для этого файла решила бы часть синхронизации.
2. Вы имеете в виду, что у каждого регистратора есть свой собственный дескриптор файла; или все они используют один дескриптор? И это многопоточно?
Ответ №1:
#include <mutex>
в C 11 это сделает. Все, что вам нужно будет сделать, это передать номер файла каждой части программе потоку
Однако имейте в виду условия гонки.
Ответ №2:
Вы могли бы добавить мьютекс в свой код ведения журнала. Это защитит его от параллелизма, потому что только один поток может заблокировать мьютекс одновременно, остальные ожидают вызова блокировки.
В UNIX вы можете использовать мьютекс p_threads, а в Win32 — критические разделы.
CRITICAL_SECTION my_mutex;
void initialise()
{
InitializeCriticalSection(amp;my_mutex);
}
void log(const char *some text)
{
EnterCriticalSection(amp;my_mutex);
// do some logging
LeaveCriticalSection(amp;my_mutex);
}
В UNIX все то же самое, за исключением использования:
pthread_mutex_t my_mutex;
pthread_mutex_init(amp;my_mutex, NULL); /// instead of InitializeCriticalSection()
pthread_mutex_lock(amp;my_mutex); /// instead of EnterCriticalSection()
pthread_mutex_unlock(amp;my_mutex); /// instead of LeaveCriticalSection()
Ответ №3:
Реализуйте потокобезопасную очередь, все компоненты вашего приложения будут отправлять сообщения журнала в вашу очередь. Из этой очереди всплывающие сообщения и запись в ваш файл журнала.
Ответ №4:
Мьютекс — это переносимый и гарантированный подход.
Хотя это и не гарантировано, в обычных реализациях выходные данные любой отдельной ofstream << x
операции никогда не смешиваются с операциями других потоков в том же потоке ( fstream
т. Е. Предположительно Используется мьютекс или тщательно сконструированная внутренняя очередь без блокировок), поэтому, если вы избегаете этого…
my_ofstream << x << y << 'n'; // troublesome: 3 fstream operations
… в пользу этого…
std::ostringstream oss;
oss << x << y << 'n';
my_ofstream << oss.rdbuf(); // usually ok: 1 fstream operation
… вы можете сохранить свои выходные строки вместе. Для ведения журнала это часто легко организовать централизованно внутри макросов ведения журнала. Для распределенного файлового ввода-вывода это неприятность. Подготовка данных в локальном ostringstream
файле, а затем их копирование — это явно больше работы в целом, но, по крайней мере, такая работа может выполняться многими потоками одновременно, при этом копирование в один ofstream
объект выполняется очень быстро. Для реализаций, которые используют некоторую внутреннюю синхронизацию, обертывание вашей собственной внешней синхронизации вокруг вашей очереди в очереди приведет к ненужному замедлению работы.