2016-04-06 11 views
0

Ich muss stdout in meiner Logging-Anwendung zu sperren, um String-Interleaving in Multi-Thread-Anwendungen zu verhindern, die auf stdout protokollieren. Kann nicht herausfinden, wie man move constructor oder std :: move oder etw sonst benutzt um unique_lock in ein anderes Objekt zu verschieben.C++ Sperren Stream-Operatoren mit Mutex

Ich erstellte Objekte zum Festlegen von Konfigurationen und Verkapselungen und fand heraus, wie man stdout mit statischem std :: mutex sperren kann, um von diesen Objekten (sogenannten Shards) zu sperren.

So etwas wie das funktioniert für mich:

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

Während die fein und könnte mit Vorlagen und variable Anzahl von Parametern realisiert wird ich mehr Strom artige Möglichkeiten nähern möchte. Ich bin auf der Suche nach so etwas wie folgt aus:

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

Ich möchte nicht um Benutzer zwingen Zeichenfolge vorauszuberechnen mit Verkettung und to_string (42) Ich will nur einen Weg finden, stdout zu sperren.

Meine bisherige Vorgehensweise war, Operator < < und einen anderen Objekt gesperrten Stream zu erstellen, wie in anderen Antworten vorgeschlagen wurde. Dinge sind, ich kann nicht herausfinden, wie man Mutex zu einem anderen Objekt bewegt. Mein Code:

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; 
} 

Nach dem Ausgeben der Eingabe an Std :: Cout möchte ich Sperre in Objektstrom verschieben.

+1

Nicht sicher, ob der Kommentar geschätzt wird, aber was ich in dieser Situation tun würde, ist Logging auf einen anderen Thread zu entladen. Der Protokollierungsthread wird ohne Sperren in stdout geschrieben, während die anderen Threads die Nachrichten über eine blockierungsfreie Warteschlange senden können. Viel weniger Konflikte und mehr Durchsatz und keine Notwendigkeit für Websperren durch Stream-Operationen. Ich werde trotzdem eine Antwort hinzufügen. –

+0

Ich weiß es zu schätzen! Ich werde versuchen, Ihre Antwort und den vorhandenen Code zusammenzuführen, behalte aber Ihren Vorschlag im Hinterkopf! Könnte auch versuchen, es später so umzuschreiben. – MarcusSK

Antwort

0

In diesem Fall würde ich vorsichtig sein, keine statischen Sperren in Funktionen zu verwenden, da Sie für jeden von Ihnen erstellten Stream-Operator eine andere Sperre erhalten.

Sie müssen eine "Ausgabesperre" sperren, wenn ein Stream erstellt wird, und sie entsperren, wenn der Stream zerstört wird. Sie können vorhandene Stream-Operationen wieder in den Status piggie einfügen, wenn Sie nur std :: ostream umschließen. Hier ist eine funktionierende Implementierung:

#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; 
} 

hier auf ideone ist: https://ideone.com/HezJBD

Auch verzeihen Sie mir, aber es wird dort eine Mischung aus Leerzeichen und Tabulatoren sein, weil der Online-Redakteure peinlich zu sein.

+0

Tausend Dank! scheint wie ein Charme zu arbeiten! – MarcusSK