2017-04-15 36 views
0

したがって、Log :: writeメソッドを呼び出すことで、同じファイルに複数のスレッドを書き込んでいます。C++:マルチスレッドプログラムのファイルに書き込む

class Log 
{ 
private: 
    ofstream log; 
    string file_path; 
public: 
    Log(string); 
    void write(string); 
}; 
Log::Log(string _file_path) 
{ 
    file_path=_file_path; 
} 
void Log::write(string str) 
{ 
    EnterCriticalSection(&CriticalSection); 
    log.open(file_path.c_str(),std::ofstream::app); 
    log<<str+'\n'; 
    log.close(); 
    LeaveCriticalSection(&CriticalSection); 
} 

スレッドが同じオブジェクトのLog :: writeメソッドを同時に呼び出すのは安全ですか?

+1

はい。 RAIIを使用してクリティカルセクションのロック/ロック解除を検討し、例外を安全にしてください。 C++の標準ロックの使用を検討してください。別のロギングスレッドとメッセージキューを使用して、ロッキングボトルネックを小さくすることを検討してください。 MS Windows上のファイルを開くことは、非常に高価な操作です - ロギングクラスをシングルトンに変更し、一度だけファイルを開くことを検討してください。 –

+1

3rdpartyロギングライブラリの使用を検討する – ZivS

答えて

1

あなたのコードは無駄であり、C++の慣用句に従いません。

最後から:yes、writeはスレッドセーフです。これは、win32 CRITICAL_SECTIONが同時変更から保護するためです。

ものの:

  1. なぜオープンし、ストリームを毎回閉じますか?これは非常に無駄なことです。コンストラクタでストリームを開き、開いたままにします。デストラクタはストリームを閉じることに対処します。

  2. Win32クリティカルセクションを使用する場合は以上、はRAIIを安全にします。クリティカルセクションへの参照をラップするクラスを作成し、コンストラクタでロックし、デストラクタでロックを解除します。例外がスローされてもこの方法でロックがロックされることが保証されます。とにかくCriticalSectionの減速はどこですか? Logのメンバーである必要があります。

  3. あなたはstd::mutexを認識していますか?

  4. なぜ文字列を値渡ししていますか?非常に効率的ではありません。 const参照を渡します。

  5. 変数の一部(file_path)ではsnake_caseを使用しますが、他の場合は上部ラクテルケース(CriticalSection)を使用します。同じ慣習を使用してください。

  6. strは、決して文字列変数の適切な名前ではなく、ファイルストリームはログではありません。実際のロギングを行うものです。 loggerはより良い名前です。私の修正ではそれはちょうどm_file_streamと命名されています。

修正されたコード:

class Log 
{ 

private: 

    std::mutex m_lock; 
    std::ofstream m_file_stream; 
    std::string m_file_path; 

public: 

    Log(const std::string& file_path); 
    void write(const std::string& log); 
}; 

Log::Log(const std::string& file_path): 
    m_file_path(file_path) 
{ 
    m_file_stream.open(m_file_path.c_str()); 
    if (!m_file_stream.is_open() || !m_file_stream.good()) 
    { 
     //throw relevant exception. 
    } 
} 

void Log::write(const std::string& log) 
{ 
    std::lock_guard<std::mutex> lock(m_lock); 
    m_file_stream << log << '\n'; 
} 
関連する問題