ラチェット・フリークの答えは、私も最初に考えたものです。
別の方法として、各モジュールに独自のプロデューサー/コンシューマーキューを割り当て、ロガーメカニズムにこれらのキューを独自のスレッドでスキャンさせる方法があります。
使用するロガーの数を切り替えることができるため、これはより柔軟になる可能性があります-すべてに1つ、各モジュールに1つ、またはモジュールをグループに分割して、各グループに1つ持つことができます。
編集:エラボレーション
(私のCを気にしないでください-それはあなたがコーディングしているとあなたが言ったことですよね?)
したがって、このアイデアは、モジュールごとにプロデューサー/コンシューマーキュー/リストを作成することです。このようなキューは、おそらく次のようになります。
enum LogItemType {INFO, ERROR};
struct LogItem
{
LogItemType type;
char *msg;
};
struct LogQueue {...}; // implementation details -- holds an array/list of LogItem
bool queueLogItem(log_queue *, log_item *);
bool queueHasItems(log_queue *);
bool queueIsFull(log_queue *);
LogItem *dequeueLogItem(log_queue *);
各モジュールは、そのような独自のキューを初期化するか、スレッドなどを設定する初期化コードによって渡される必要があります。初期化コードは、おそらくすべてのキューへの参照を保持する必要があります。
LogQueue *module_queues = {module_1_queue_ptr, module_2_queue_ptr, ... , module_N_queue_ptr};
setModuleLoggingQueue(module1, module_1_queue_ptr);
// .
// .
// .
モジュール内では、LogItemを作成して、メッセージごとにキューに入れます。
LogItem *item = malloc(sizeof(LogItem));
item->type = INFO;
item->msg = malloc(MSG_SIZE)
memcpy("MSG", item->msg);
queueLogItem(module_queue, item);
次に、メッセージを受け取り、実際にメインループでログを書き込むキューの1つ以上のコンシューマーが存在します。
void loggingThreadBody()
{
while (true)
{
for (i = 0; i < N; i++)
{
if (queueHasItems(module_queues[i]))
writeLogItem(dequeueLogItem(module_queues[i]));
}
threadSleep(200);
}
}
またはそのようなもの。
これにより、キューのさまざまなコンシューマを使用できるようになります。たとえば、次のようになります。
// For one logger:
LogQueue *module_queues = {module_1_queue_ptr, module_2_queue_ptr, ... , module_N_queue_ptr};
initLoggerThread(module_queues);
// -OR-
// For multiple loggers:
LogQueue *group1_queues = {module_1_queue_ptr, ..., module_4_queue_ptr};
LogQueue *group2_queues = {module_5_queue_ptr, ... , module_Nmin7_queue_ptr};
LogQueue *group3_queues = {module_Nmin7_queue_ptr, ... , module_N_queue_ptr};
initLoggerThread(group1_queues);
initLoggerThread(group2_queues);
initLoggerThread(group3_queues);
注:キュー時にログメッセージ用のメモリを割り当て、消費時にメモリの割り当てを解除する必要があると思います(メッセージに動的コンテンツが含まれている場合)。
別の編集:
言及を忘れた:モジュールスレッドで多くのアクティビティを期待している場合は、ログ書き込みを非同期で実行して、ブロックされないようにできるかどうかを確認できます。
さらに別の編集:
また、LogItemの一部としてタイムスタンプを配置することもできます。ロガースレッドがキューを順番に通過するため、ログステートメントがモジュールで発生順に発生したときから、ログステートメントの順序が乱れる場合があります。
そしてさらに別の編集:
この設定では、すべてのモジュールに同じキューを渡し、消費者にその1つのキューを表示させるだけでかなり簡単になり、ラチェットフリークの答えに戻ることができます。
Geeze、編集をやめてくれないか!?:
また、モジュールのグループごとに1つのキューを用意し、各キューにロガーを用意することもできます。
よし、やめよう。