30 Thread support library [thread]

30.4 Mutual exclusion [thread.mutex]

30.4.2 Locks [thread.lock]

30.4.2.1 Class template lock_guard [thread.lock.guard]

namespace std {
  template <class... MutexTypes>
  class lock_guard {
  public:
    using mutex_type = Mutex;  // If MutexTypes... consists of the single type Mutex

    explicit lock_guard(MutexTypes&... m);
    lock_guard(MutexTypes&... m, adopt_lock_t);
    ~lock_guard();

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

  private:
    tuple<MutexTypes&...> pm; // exposition only
  };
}

An object of type lock_guard controls the ownership of lockable objects within a scope. A lock_guard object maintains ownership of lockable objects throughout the lock_guard object's lifetime ([basic.life]). The behavior of a program is undefined if the lockable objects referenced by pm do not exist for the entire lifetime of the lock_guard object. When sizeof...(MutexTypes) is 1, the supplied Mutex type shall meet the BasicLockable requirements. Otherwise, each of the mutex types shall meet the Lockable requirements ([thread.req.lockable.basic]).

explicit lock_guard(MutexTypes&... m);

Requires: If a MutexTypes type is not a recursive mutex, the calling thread does not own the corresponding mutex element of m.

Effects: Initializes pm with tie(m...). Then if sizeof...(MutexTypes) is 0, no effects. Otherwise if sizeof...(MutexTypes) is 1, then m.lock(). Otherwise, then lock(m...).

lock_guard(MutexTypes&... m, adopt_lock_t);

Requires: The calling thread owns all the mutexes in m.

Effects: Initializes pm with tie(m...).

Throws: Nothing.

~lock_guard();

Effects: For all i in [0, sizeof...(MutexTypes)), get<i>(pm).unlock().