samedi 17 avril 2021

C++11's "const==mutable", non-const == unprotected == efficient when needed?

As I introduced also in this question, C++11 saga of const/mutable, Provide two classes for efficiency? , in C++98, or before threads, albeit incorrect in some contexts, it was common to write class with internal hidden using mutable.

In C++11 Herb Sutter said that from now on const == thread safe, meaning that the the mutable fields should be protected by a mutex.

so I though that some one that really know what he/she is doing can actually a more general version of the single class by doing something special in the non-const case.

struct Widget {
private:
  int getValue_aux() const{
    if (cacheValid) return cachedValue;
    else {
      cachedValue = expensiveQuery(); // write data mem
      cacheValid = true;                    // write data mem
      return cachedValue;
    }
  }
public:
  int getValue() {
    return get_value_aux();  // no lock
  }                                    
  int getValue() const{
    std::lock_guard<std::mutex> guard{m}; // lock mutex
    get_value_aux();
  }                                      // unlock mutex
...
  private:
  mutable std::mutex m;
  mutable int cachedValue;
  mutable bool cacheValid;
...
};

So, a) a normal user can use a non-const instance of Widget to mark that it is not intended to be used in a thread safe context, and not pay for the mutex-locking b) A user-that-really-knows-what-he-is-doing can const_cast or wrap it as mutable if he knows that thread safety is not going to be an issue on a particular point in the code (he/she is still storing a mutex though).

Is this a reasonable generalization of Widget at all? Or is it flawed?


Note: If you think that const and non-const versions should be provided for efficiency, you my find this question also interesting: C++11 saga of const/mutable, How to implement copy? and efficiently?

Aucun commentaire:

Enregistrer un commentaire