32 Thread support library [thread]

32.5 Mutual exclusion [thread.mutex]

32.5.4 Locks [thread.lock]

32.5.4.2 Class template scoped_­lock [thread.lock.scoped]

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

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

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

  private:
    tuple<MutexTypes&...> pm;   // exposition only
  };
}
An object of type scoped_­lock controls the ownership of lockable objects within a scope.
A scoped_­lock object maintains ownership of lockable objects throughout the scoped_­lock object's lifetime.
The behavior of a program is undefined if the lockable objects referenced by pm do not exist for the entire lifetime of the scoped_­lock object.
When sizeof...(MutexTypes) is 1, the supplied Mutex type shall meet the Cpp17BasicLockable requirements ([thread.req.lockable.basic]).
Otherwise, each of the mutex types shall meet the Cpp17Lockable requirements ([thread.req.lockable.req]).
explicit scoped_lock(MutexTypes&... m);
Preconditions: 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, lock(m...).
explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
Preconditions: The calling thread owns all the mutexes in m.
Effects: Initializes pm with tie(m...).
Throws: Nothing.
~scoped_lock();
Effects: For all i in [0, sizeof...(MutexTypes)), get<i>(pm).unlock().