Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

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

NAME
       std::lock - std::lock

Synopsis
	  Defined in header <mutex>
	  template<  class  Lockable1,	class  Lockable2, class... LockableN >
       (since C++11)
	  void lock( Lockable1&	lock1, Lockable2& lock2,  LockableN&...	 lockn
       );

	  Locks	 the  given  Lockable objects lock1, lock2, ..., lockn using a
       deadlock	avoidance
	  algorithm to avoid deadlock.

	  The objects are locked by an unspecified series of  calls  to	 lock,
       try_lock, and
	  unlock.  If a	call to	lock or	unlock results in an exception,	unlock
       is called for
	  any locked objects before rethrowing.

Parameters
	  lock1, lock2,	... , lockn - the Lockable objects to lock

Return value
	  (none)

Notes
	  Boost	provides a version of this function that takes a  sequence  of
       Lockable	objects
	  defined by a pair of iterators.

	  std::scoped_lock  offers  a  RAII  wrapper for this function,	and is
       generally preferred
	  to a naked call to std::lock.

Example
	  The following	example	uses std::lock to lock pairs of	mutexes	 with-
       out deadlock.

       // Run this code

	#include <mutex>
	#include <thread>
	#include <iostream>
	#include <vector>
	#include <functional>
	#include <chrono>
	#include <string>

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

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

	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::lock to	acquire	two locks without worrying about
	    // other calls to assign_lunch_partner deadlocking us
	    {
		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 (if unique_locks are	 needed,  e.g.	for  condition
       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);
	// Superior solution available in C++17
	//	  std::scoped_lock lk(e1.m, e2.m);
		{
		    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
       assignments
	    // 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.output()	<< '\n'	 << bob.output() << '\n'
		      << christina.output() << '\n' << dave.output() <<	'\n';
	}

Possible output:
	alice and bob are waiting for locks
	alice and bob got locks
	christina and bob are waiting for locks
	christina and bob got locks
	christina and alice are	waiting	for locks
	christina and alice got	locks
	dave and bob are waiting for locks
	dave and bob got locks
	Employee alice has lunch partners: bob christina
	Employee bob has lunch partners: alice christina dave
	Employee christina has lunch partners: bob alice
	Employee dave has lunch	partners: bob

See also
	  unique_lock implements movable mutex ownership wrapper
	  (C++11)     (class template)
	  try_lock    attempts to obtain ownership  of	mutexes	 via  repeated
       calls to	try_lock
	  (C++11)     (function	template)
	  scoped_lock deadlock-avoiding	RAII wrapper for multiple mutexes
	  (C++17)     (class template)

http://cppreference.com		  2022.07.31			  std::lock(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=std::lock&sektion=3&manpath=FreeBSD+Ports+15.0>

home | help