2016-11-13 3 views
2

Ich verwende eine std::condition_variable kombiniert mit einer std::unique_lock wie folgt.Ist es möglich, std :: condition_variable mit std :: lock_guard zu verwenden?

std::mutex a_mutex; 
std::condition_variable a_condition_variable; 
std::unique_lock<std::mutex> a_lock(a_mutex); 
a_condition_variable.wait(a_lock, [this] {return something;}); 
//Do something 
a_lock.unlock(); 

Es funktioniert gut. Wie ich es verstehe, std::condition_variable akzeptiert eine std::unique_lock für sie zu warten. Aber ich versuche es mit std::lock_guard zu kombinieren, aber nicht in der Lage dazu.

Meine Frage ist:Ist es möglich, std::unique_lock mit einem std::lock_guard statt zu ersetzen? Das kann mich entlasten von der manuellen Entriegelung des Schlosses jedes Mal, wenn ich es benutze.

Antwort

2

Nein, ein std::unique_lock benötigt wird, wenn es mit std::condition_variable verwendet wird. std::lock_guard möglicherweise weniger Overhead, aber es kann nicht mit std::condition_variable verwendet werden.

Aber die std::unique_lock muss nicht manuell entsperrt werden, es wird auch entsperrt, wenn es den Gültigkeitsbereich verlässt, wie std::lock_guard. So könnte die Warte Code geschrieben werden als:

std::mutex a_mutex; 
std::condition_variable a_condition_variable; 
{ 
    std::unique_lock<std::mutex> a_lock(a_mutex); 
    a_condition_variable.wait(a_lock, [this] {return something;}); 
    //Do something 
} 

Siehe http://en.cppreference.com/w/cpp/thread/unique_lock

2

unmöglich, aber Sie nicht wirklich, dass benötigen.

std::unique_lock automatisch unlocks itself in destructor, wenn es gesperrt wurde.

+0

Dank für eine solche schnelle Klärung. Beide Antworten sind akzeptabel. Wählen Sie einfach eine der beiden –

3

Jeder Aufruf wait() auf einer Zustandsgröße immer lock() benötigen und unlock() die mutex zugrunde liegen. Da die Hülle lock_guard<> diese Funktionen nicht zur Verfügung stellt, kann es nie mit wait() verwendet werden.

Noch könnten Sie Ihre eigenen einfachen Mutex-Wrapper schreiben basierend auf lock_guard<>, und fügen Sie die 2 notwendigen Methoden. Außerdem müssten Sie condition_variable_any verwenden, die mit einem Schloss aus jedem Schloss/Mutex akzeptiert()/entsperren() Schnittstelle:

#include <mutex> 

template<typename _mutex_t> 
class my_lock_guard 
{ 
public: 
    explicit my_lock_guard(_mutex_t & __m) : __mutex(__m) 
    { __mutex.lock(); } 

    my_lock_guard(_mutex_t & __m, std::adopt_lock_t) : __mutex(__m) 
    { } // calling thread owns mutex 

    ~my_lock_guard() 
    { __mutex.unlock(); } 

    void lock() 
    { __mutex.lock(); } 

    void unlock() 
    { __mutex.unlock(); } 

    my_lock_guard(const my_lock_guard &) = delete; 
    my_lock_guard& operator=(const my_lock_guard &) = delete; 

private: 
    _mutex_t & __mutex; 
}; 

Und dann:

#include <condition_variable> 
... 
std::mutex m; 
my_lock_guard<std::mutex> lg(m); 
std::condition_variable_any cva; 
cva.wait(lg, [] { return something;}); 
// do something ... 
... 
+1

Ich kann nicht scheinen, 'lock_guard' mit' condition_variable_any' zu arbeiten. Die Fehlermeldung sagt etwas über fehlende Memberfunktionen 'lock()' und 'unlock()'. Warum das? –

+0

Können Sie weitere Details hinzufügen (Compiler, Fehlermeldung, Code)? Vielleicht wäre es auch sauberer, eine neue Frage zu stellen. –

+1

Ich benutzte Ihren ersten Code, fügte hinzu, 'main' und änderte das Lambda, um' 'true'' zurückzugeben. Ich verwende den neuesten von macOS gelieferten Klang. Hier sind die Fehlermeldungen: http://codepad.org/8Xvh8O1m Kompiliert Ihr Code für Sie? Mit welchem ​​Compiler? –

Verwandte Themen