5

I'm building a simple { mutex, value } pair as follows, and I'd like to check with c++ lawyers if my use case is well defined.

Tool definition

template<typename T, class mutex> class Locker;

template<typename T, class mutex>
class Mutexed
{
    T     _value;
    mutex _mutex;
    friend class Locker<T, mutex>;
public:
    Mutexed() {}
    Mutexed(const T& init)           : _value(init) {}
    Mutexed(const Mutexed<T>& other) : _value(other._value) {}
};

template<typename T, class mutex>
class Locker
{
    Mutexed<T, mutex>& _mutexed;
public:
    Locker(Mutexed<T, mutex>& mutexed) : _mutexed(mutexed) { _mutexed.mutex.lock(); }
    ~Locker() { _mutexed.mutex.unlock(); }
    const T& operator*() const { return _mutexed.value; }
          T& operator*()       { return _mutexed.value; }
};

Use case

Mutexed<int, MyMutex> answer(42);
int getAnswer() { Locker<int> lock(answer); return *lock; }

My concern

Since *lock, id est const T& operator*() const { return _mutexed.value; } returns a reference to answer._value, a copy from int& to int is made. But since, lock goes out of scope while returning: which of the copy and the mutex unclock will happen first?

tl;dr

Is my usecase not UB xor do I need to write?

const int result = *lock;
return result;
Community
  • 1
  • 1
YSC
  • 38,212
  • 9
  • 96
  • 149
  • @NathanOlivier Thank you for the duplicate. it's a nice find! – YSC Apr 11 '17 at 14:15
  • 1
    Note that if destructor happened before the copy, you'd never be able to return a local object from a function. – Barry Apr 11 '17 at 14:34
  • @Barry Stated like that, it sounds so obvious: it should be an (accepted) answer. – YSC Apr 11 '17 at 14:40

0 Answers0