2017-12-07 10 views
1


Was kann Mutable in C++ tun?

Ich bekam diesen Code für die sequentielle Programmierung und Lock-Programmierung. Ich muss den Unterschied analysieren, aber ich bin mir nicht sicher, was ein Teil des Codes tut. Der Code ist unten, und die Teile, die ich nicht verstehe, werden auch in den Kugeln erwähnt.

  • Wirkung von Stichwort: Veränderliche
    • Eine andere Antwort sagt, dass Stackoverflow wandelbar ein const modifiziert zu sein
      erlaubt, aber ich sehe nicht, was das mit diesem Projekt zu tun hat
    • Was das ist Effekt des Entfernens "veränderbar" in diesem Programm? Deaktiviert es die Sperren?
  • Mutable für not_full und not_empty
    • meinen Mangel an Verständnis für diese Förderung, warum wandelbar ist nicht für not_full und not_empty erforderlich?

Vielen Dank für das Lesen, wäre jede Hilfe dankbar!

<pre><code> 
    #ifndef LOCKEDBUFFER_H 
    #define LOCKEDBUFFER_H 

    #include <memory> 
    #include <mutex> 
    #include <condition_variable> 
    #include <atomic> 

    #include "optional.h" 

    template <typename T> 
    class locked_buffer { 
    public: 
     // Creates buffer of size n 
     locked_buffer(int n) : 
     size_{n}, 
     buf_{new optional<T>[size_]} 
     { 
     } 

     // Remove copy constructor 
     locked_buffer(const locked_buffer &) = delete; 

     // Destructor (default generated) 
     ~locked_buffer() = default; 

     // Gets buffer size 
     int size() const noexcept { 
     return size_; 
     } 

     // Checks if buffer is empty 
     bool empty() const noexcept { 
     std::lock_guard<std::mutex> l{mut_}; 
     return is_empty(); 
     } 

     // Checks if buffer is full 
     bool full() const noexcept { 
     std::lock_guard<std::mutex> l{mut_}; 
     return is_full(); 
     } 

     // Put an optional value in the queue 
     void put(const optional<T> & x); 

     // Get a value from the queue 
     optional<T> get(); 

    private: 
     // Next circular position to position p 
     int next_position(int p) const noexcept { 
     return p + ((p+1>=size_)?(1-size_):1); 
     } 

     // Check if buffer is empty without locking 
     bool is_empty() const noexcept { 
     return (next_read_ == next_write_); 
     } 

     // Check if buffer is full without locking 
     bool is_full() const noexcept { 
     const int next = next_position(next_write_); 
     return next == next_read_; 
     } 

    private: 
     const int size_; 
     const std::unique_ptr<optional<T>[]> buf_; 
     int next_read_ = 0; 
     int next_write_ = 0; 

     mutable std::mutex mut_; 
     std::condition_variable not_full_; 
     std::condition_variable not_empty_; 
    }; 


    template <typename T> 
    void locked_buffer<T>::put(const optional<T> & x) 
    { 
     using namespace std; 
     unique_lock<mutex> l{mut_}; 
     not_full_.wait(l, [this] { return !is_full(); }); 
     buf_[next_write_] = x; 
     next_write_ = next_position(next_write_); 
     not_empty_.notify_one(); 
    } 

    template <typename T> 
    optional<T> locked_buffer<T>::get() 
    { 
     using namespace std; 
     unique_lock<mutex> l{mut_}; 
     not_empty_.wait(l, [this] { return !is_empty(); }); 
     auto res = buf_[next_read_]; 
     next_read_ = next_position(next_read_); 
     not_full_.notify_one(); 
     return res; 
    } 

    #endif 
+1

Ich denke, es ist zu ermöglichen, den Mutex auch in 'const' Methoden zu sperren – user463035818

+1

' mutable' hat nichts mit Sperren zu tun; Wird es aus diesem Code entfernt, führt dies höchstens dazu, dass es nicht kompiliert werden kann. –

+0

http://en.cppreference.com/w/cpp/language/cv kann hilfreich sein. –

Antwort

3

Lassen Sie uns Schritt für Schritt durchgehen.

Eine andere Antwort sagt, dass Stackoverflow wandelbar ein const modifiziert sein können, aber ich sehe nicht, was das

mit diesem Projekt zu tun hat, Dies gilt irgendwie auf Ihre Klasse gelten. Sie haben diese Methode.

bool empty() const noexcept { 
    std::lock_guard<std::mutex> l{mut_}; 
    return is_empty(); 
} 

Die lock guard erwartet eine nicht const Objektreferenz als lock_guard die mutex ändern. Aber da Ihre Methode const ist, können Sie auf kein Mitglied auf eine nicht konstante Weise zugreifen. Hier kommt Mutable ins Spiel.

Was bewirkt das Entfernen von "veränderbar" in diesem Programm? Werden die Sperren deaktiviert?

Wenn Sie die wandelbar entfernen von Ihrem mutex Sie einen Compiler-Fehler in der empty() und der full() Methode erhalten. Also technisch sind die Schlösser nicht gesperrt, aber Ihr Programm ist schlecht ausgebildet.

Fördem mein Mangel an Verständnis dieser, warum Mutable nicht für not_full und not_empty erforderlich ist?

Nun, einfach weil sie in nicht konstanten Methoden verwendet werden.
Also keine Notwendigkeit, sie veränderbar zu machen. Wenn Sie eine von ihnen in einer Konst-Methode verwenden würden und Sie möchten eine Nicht-Konst-Methode für die condition_variable verwenden, dann müssten Sie sie änderbar machen.