5

Lets consider such a class in C++:

class CuteClass
{
public:
  int    getFancyInt() const;
  float  getNiceFloat() const;
  string getPerfectString() const;

  void setIntSomething(int something);
  void setInternalState(State newState);
};

The instance of this class could be accessed concurrently from several different threads. And then:

All getMethods (getFancyInt, getNiceFloat, getPerfectString) shouldn't block each other. They doesn't change the internal state of the object.

All setMethod (setIntSomething, setInternalState) should:

  • block each other - to avoid inconsistent state of object,
  • block all getMethods - to avoid returning partially changed data,
  • be blocked by all getMethods - to avoid returning partially changed data.

A simple lock_guard with mutex will met all requirements except one - getMethod would then block other getMethods.

What solution would be easy and clean in such scenario?

Dejwi
  • 4,393
  • 12
  • 45
  • 74
  • possible duplicate of [Reader/Writer Locks in C++](http://stackoverflow.com/questions/244316/reader-writer-locks-in-c) – Amit Sep 06 '15 at 09:01

2 Answers2

7

What you are loonking for is a R/W mutex.

You lock it as "READ" in all your getter and "WRITE" in all your setter.

Boost shared_mutex is what you are looking for

Example for boost shared_mutex (multiple reads/one write)?

In order to be compatible with your "const" declarations, you need to declare the mutex itself as mutable

Community
  • 1
  • 1
adev
  • 146
  • 4
3

std::atomic should resolve any concern about partly changed data.

[Edited:] No, it doesn't. If I don't delete this wrong answer it's only for the insightful comments that should be preserved.

Joachim W
  • 7,290
  • 5
  • 31
  • 59
  • Atomic is a valid solution only in case of internal basic types. For complex type or multiples types, you can still have race conditions – adev Sep 06 '15 at 09:06
  • 2
    `std::atomic` works for user defined types as well, but might involve a lock. – Bo Persson Sep 06 '15 at 10:45
  • 1
    This does not address the internal state of the object being consistent when read. See the OP point `block all getMethods - to avoid returning partially changed data` – Richard Critten Sep 06 '15 at 11:16
  • 1
    `std::atomic` has the wrong granularity for this problem. For example, `setInternalState` may very well atomically modify "fancy int", then atomically modify "fancy float". But that's not enough. You want to lock the *entire* sequence of events, such that clients never see the modification of the int before the modification of the float. – Christian Hackl Sep 06 '15 at 12:57