自身でログをやって、すべてのスレッドが明示的にミューテックスを使用する必要がありますなぜ私はかなり理解していません。
ディスクファイルにロギングしている場合は、すべてのスレッドが独自のファイルにロギングできます。あなたは、共通の接頭辞を持つファイルに名前を付けることができます。
QFile * logFile(QObject * parent = nullptr) {
auto baseName = QStringLiteral("MyApplication-");
auto threadName = QThread::currentThread()->objectName();
if (threadName.isEmpty())
return new QTemporaryFile(baseName);
else
return new QFile(baseName + threadName);
}
オペレーティングシステムは、そのファイルシステムのミューテックス(ES)を経由してアクセスをシリアル化されます。
適切な並行処理オプションが選択されたsqliteなど、並行アクセスをサポートするデータベースにロギングする場合、データベースドライバはシリアル化アクセスを処理します。
共通スレッドにログを記録している場合、イベントキューには、postEvent
のときに自動的にシリアライズするmutexがあります。
シグナルスロットメカニズムを使用しても、イベントを直接使用することはあまりありません。実際には、より多くのメモリ割り当てを行うことが保証されているので、自分でイベントを投稿することをお勧めします。理想的には、ログメッセージの「最も」に適合するサイズのQVarLengthArray<char>
を使用するイベントです。
// logger.h
struct MyLogEvent : QEvent {
constexpr static QEvent::Type theType() { return (QEvent::Type)(QEvent::User + 1); }
QVarLengthArray<char, 128> message;
MyLogEvent(const char * msg) : QEvent(theType()) {
message.append(msg, strlen(msg));
}
};
class Logger : public QObject {
...
public:
static void log(const char * msg) {
QCoreApplication::postEvent(instance(), new MyLogEvent(msg));
}
static Logger * instance(); // singleton, must be a thread safe method
};
// logger.cpp
...
Q_GLOBAL_STATIC(Logger, loggerInstance);
Logger * Logger::instance() {
// Thread-safe since QGlobalStatic is.
return loggerInstance;
}
はあなたがQByteArray
やQString
を使用していた、表現new MyLogEvent
は、少なくとも2つの割り当てを行っているだろう。そこで、このようなイベントは、単一のmalloc
の呼び出しで行われ割り振ります。
あるレベルでは、すべての場合に同期が必要です(つまり、mutexes)。だから問題は、ロガースレッドは、イベントソースのスレッドで作業を実行するだけでなく、イベントを書き込むために十分長い間、イベントのデータを何らかのキューにマーシャリングするコストを正当化するために、イベントごとに十分な作業を行う必要があるかどうかです。データを共通出力に出力します。 – nate
専用のロギングスレッド(暗黙的かもしれませんが、他のスレッドからのイベントやポストはどこかにキューイングされている必要があります)は同期が必要です。 –
@JesperJuhl非パラレルロギングは実行時の動作を変更します(多すぎるような場合(たとえば、何らかの動作をデバッグするためにログレベルが上がった場合など)。専用のロギングスレッドを使用しないと、ログエントリ*を書き込んでいる間に他のスレッドが常にログを記録しないようにするか、混乱させる混乱したログを受け入れる必要があります。 –