home | help
std::scoped_lock(3)	       C++ Standard Libary	     std::scoped_lock(3)

NAME
     std::scoped_lock - std::scoped_lock

Synopsis
	Defined in header <mutex>
	template< class... MutexTypes >  (since C++17)
	class scoped_lock;

	The  class  scoped_lock  is  a	mutex wrapper that provides a convenient
     RAII-style
	mechanism for owning zero or more mutexes for the duration of  a  scoped
     block.

	When  a  scoped_lock object is created, it attempts to take ownership of
     the mutexes
	it is given. When control leaves the scope in which the scoped_lock  ob-
     ject was
	created,  the scoped_lock is destructed and the mutexes are released. If
     several
	mutexes are given,  deadlock  avoidance  algorithm  is	used  as  if  by
     std::lock.

	The scoped_lock class is non-copyable.

Template parameters
		     the  types  of the mutexes to lock. The types must meet the
     Lockable
	MutexTypes - requirements unless sizeof...(MutexTypes)==1, in which case
     the only
		     type must meet BasicLockable

Member types
	Member type				Definition
	mutex_type (ifsizeof...(MutexTypes)==1) Mutex, the sole type  in  Mutex-
     Types...

Member functions
	constructor   constructs a scoped_lock, optionally locking the given mu-
     texes
		      (public member function)
	destructor     destructs  the scoped_lock object, unlocks the underlying
     mutexes
		      (public member function)
	operator=     not copy-assignable
	[deleted]     (public member function)

Notes
	A common beginner error is to "forget" to give a scoped_lock variable  a
     name, e.g.
	std::scoped_lock(mtx);	(which default constructs a scoped_lock variable
     named mtx)
	or std::scoped_lock{mtx}; (which constructs a prvalue object that is im-
     mediately
	destroyed), thereby not actually constructing a lock that holds a  mutex
     for the rest
	of the scope.

	 Feature-test macro    Value	Std	  Feature
	__cpp_lib_scoped_lock 201703L (C++17) std::scoped_lock

Example
	The  following	example  uses  std::scoped_lock to lock pairs of mutexes
     without
	deadlock and is RAII-style.

     // Run this code

      #include <chrono>
      #include <functional>
      #include <iostream>
      #include <mutex>
      #include <string>
      #include <thread>
      #include <vector>
      using namespace std::chrono_literals;

      struct Employee
      {
	  std::vector<std::string> lunch_partners;
	  std::string id;
	  std::mutex m;
	  Employee(std::string id) : id(id) {}
	  std::string partners() const
	  {
	      std::string ret = "Employee " + id + " has lunch partners: ";
	      for (int count{}; const auto& partner : lunch_partners)
		  ret += (count++ ? ", " : "") + partner;
	      return ret;
	  }
      };

      void send_mail(Employee&, Employee&)
      {
	  // Simulate a time-consuming messaging operation
	  std::this_thread::sleep_for(1s);
      }

      void assign_lunch_partner(Employee& e1, Employee& e2)
      {
	  static std::mutex io_mutex;
	  {
	      std::lock_guard<std::mutex> lk(io_mutex);
	      std::cout << e1.id << " and " << e2.id << " are waiting for locks"
     << std::endl;
	  }

	  {
	      // Use std::scoped_lock to  acquire  two	locks  without	worrying
     about
	      // other calls to assign_lunch_partner deadlocking us
	      // and it also provides a convenient RAII-style mechanism

	      std::scoped_lock lock(e1.m, e2.m);

	      // Equivalent code 1 (using std::lock and std::lock_guard)
	      // std::lock(e1.m, e2.m);
	      // std::lock_guard<std::mutex> lk1(e1.m, std::adopt_lock);
	      // std::lock_guard<std::mutex> lk2(e2.m, std::adopt_lock);

	      //  Equivalent code 2 (if unique_locks are needed, e.g. for condi-
     tion variables)
	      // std::unique_lock<std::mutex> lk1(e1.m, std::defer_lock);
	      // std::unique_lock<std::mutex> lk2(e2.m, std::defer_lock);
	      // std::lock(lk1, lk2);
	      {
		  std::lock_guard<std::mutex> lk(io_mutex);
		  std::cout << e1.id << " and " << e2.id  <<  "  got  locks"  <<
     std::endl;
	      }
	      e1.lunch_partners.push_back(e2.id);
	      e2.lunch_partners.push_back(e1.id);
	  }

	  send_mail(e1, e2);
	  send_mail(e2, e1);
      }

      int main()
      {
	  Employee     alice("Alice"),	  bob("Bob"),	 christina("Christina"),
     dave("Dave");

	  // Assign in parallel threads because mailing users  about  lunch  as-
     signments
	  // takes a long time
	  std::vector<std::thread> threads;
	  threads.emplace_back(assign_lunch_partner,		std::ref(alice),
     std::ref(bob));
	  threads.emplace_back(assign_lunch_partner,	    std::ref(christina),
     std::ref(bob));
	  threads.emplace_back(assign_lunch_partner,	    std::ref(christina),
     std::ref(alice));
	  threads.emplace_back(assign_lunch_partner,		 std::ref(dave),
     std::ref(bob));

	  for (auto& thread : threads)
	      thread.join();
	  std::cout << alice.partners() << '\n'  << bob.partners() << '\n'
		    << christina.partners() << '\n' << dave.partners() << '\n';
      }

Possible output:
      Alice and Bob are waiting for locks
      Alice and Bob got locks
      Christina and Bob are waiting for locks
      Christina and Alice are waiting for locks
      Dave and Bob are waiting for locks
      Dave and Bob got locks
      Christina and Alice got locks
      Christina and Bob got locks
      Employee Alice has lunch partners: Bob, Christina
      Employee Bob has lunch partners: Alice, Dave, Christina
      Employee Christina has lunch partners: Alice, Bob
      Employee Dave has lunch partners: Bob

	Defect reports

	The  following	behavior-changing  defect  reports were applied retroac-
     tively to
	previously published C++ standards.

	   DR	 Applied to		 Behavior as published		    Cor-
     rect behavior
	LWG 2981 C++17	    redundant deduction guide from		     re-
     moved
			    scoped_lock<MutexTypes...> was provided

See also
	unique_lock implements movable mutex ownership wrapper
	(C++11)     (class template)
	lock_guard  implements a strictly scope-based mutex ownership wrapper
	(C++11)     (class template)

http://cppreference.com 	   2024.06.10		     std::scoped_lock(3)

home | help