2016-04-06 14 views
0

マルチスレッドアプリケーションでstdoutにログを記録するのを防ぐため、ロギングアプリケーションでstdoutをロックする必要があります。移動コンストラクタやstd :: moveやsth elseを使ってunique_lockを別のオブジェクトに移動する方法を理解できません。C++ミューテックスを使用したスト​​リーム演算子のロック

configsとカプセル化を設定するためのオブジェクトを作成し、static std :: mutexでstdoutをロックしてこれらのオブジェクト(シャードと呼ばれる)からロックする方法を見つけました。このような

何かが私の作品:

l->log(1, "Test message 1"); 

それは結構ですとテンプレートと私はより多くのストリームのような可能性にアプローチしたいパラメータの可変数で実現することができますが。私はこのような何かを探しています:

*l << "Module id: " << 42 << "value: " << 42 << std::endl; 

私は連結とto_stringに(42)で文字列を事前計算することをユーザーに強制したいいけない、私はちょうどSTDOUTをロックする方法を見つけたいです。

これまでのアプローチでは、オペレータ< <と他のオブジェクトロックストリームを作成する方法がありました。私はミューテックスを別のオブジェクトに移動する方法を理解できません。私のコード:

locked_stream& shard::operator<<(int num) 
{ 
    static std::mutex _out_mutex; 
    std::unique_lock<std::mutex> lock(_out_mutex); 
    //std::lock_guard<std::mutex> lock (_out_mutex); 
    std::cout << std::to_string(num) << "(s)"; 
    locked_stream s; 
    return s; 
} 

入力をstd :: coutに出力した後、ロックをオブジェクトストリームに移動する必要があります。

+1

コメントをいただければ幸いですが、この状況では他のスレッドへのログをオフロードすることになります。ロギングスレッドはロックなしでstdoutに書き込みますが、他のスレッドはロックフリーキューでメッセージを送信できます。競合が少なく、スループットが向上し、ストリーム操作によるロックを製織する必要がありません。私は無関係に答えを加えます。 –

+0

私はそれを感謝します! 私はあなたの答えと既存のコードをマージしようとしますが、あなたの念頭に置いておきます!後でそれを書き直すこともできます。 – MarcusSK

答えて

0

この場合、関数内で静的ロックを使用しないように注意します。作成するストリーム演算子ごとに異なるロックが設定されるためです。

必要なのは、ストリームの作成時に「出力ロック」をロックし、ストリームが破棄されたときにロックを解除することです。 std :: ostreamをラップするだけの場合は、既存のストリーム操作を呼び出すことができます。ここでは作業の実装です:私を許して、https://ideone.com/HezJBD

また、しかしのでぎこちないというオンラインエディタのアップがスペースとタブの組み合わせが存在します。

#include <mutex> 
#include <iostream> 


class locked_stream 
{ 
    static std::mutex s_out_mutex; 

    std::unique_lock<std::mutex> lock_; 
    std::ostream* stream_; // can't make this reference so we can move 

public: 
    locked_stream(std::ostream& stream) 
     : lock_(s_out_mutex) 
     , stream_(&stream) 
    { } 

    locked_stream(locked_stream&& other) 
     : lock_(std::move(other.lock_)) 
     , stream_(other.stream_) 
    { 
     other.stream_ = nullptr; 
    } 

    friend locked_stream&& operator << (locked_stream&& s, std::ostream& (*arg)(std::ostream&)) 
    { 
     (*s.stream_) << arg; 
     return std::move(s); 
    } 

    template <typename Arg> 
    friend locked_stream&& operator << (locked_stream&& s, Arg&& arg) 
    { 
     (*s.stream_) << std::forward<Arg>(arg); 
     return std::move(s); 
    } 
}; 

std::mutex locked_stream::s_out_mutex{}; 

locked_stream locked_cout() 
{ 
    return locked_stream(std::cout); 
} 

int main (int argc, char * argv[]) 
{ 
    locked_cout() << "hello world: " << 1 << 3.14 << std::endl; 
    return 0; 
} 

ここでは、ideoneです。

+0

千年ありがとう!魅力のように働くようです! – MarcusSK

関連する問題