std::defer_lock, std::try_to_lock, std::adopt_lock, std::defer_lock_t, std::try_to_lock_t, std::adopt_lock_t
From cppreference.com
Defined in header <mutex> | ||
struct defer_lock_t {explicit defer_lock_t()=default;}; | (1) | (since C++11) |
constexprstd::defer_lock_t defer_lock {}; | (2) | (since C++11) (inline since C++17) |
struct try_to_lock_t {explicit try_to_lock_t()=default;}; | (3) | (since C++11) |
constexprstd::try_to_lock_t try_to_lock {}; | (4) | (since C++11) (inline since C++17) |
struct adopt_lock_t {explicit adopt_lock_t()=default;}; | (5) | (since C++11) |
constexprstd::adopt_lock_t adopt_lock {}; | (6) | (since C++11) (inline since C++17) |
1,3,5) The empty class tag types
std::defer_lock_t
, std::try_to_lock_t
and std::adopt_lock_t
can be used in the constructor's parameter list for std::unique_lock and std::shared_lock to specify locking strategy. 2,4,6) The corresponding
std::defer_lock
, std::try_to_lock
and std::adopt_lock
instances of (1,3,5) can be passed to the constructors to indicate the type of locking strategy.One of the constructors of the class template std::lock_guard only accepts the tag std::adopt_lock
.
Type | Effect(s) |
defer_lock_t | do not acquire ownership of the mutex |
try_to_lock_t | try to acquire ownership of the mutex without blocking |
adopt_lock_t | assume the calling thread already has ownership of the mutex |
[edit]Example
Run this code
#include <iostream>#include <mutex>#include <thread> struct bank_account {explicit bank_account(int balance): balance{balance}{}int balance;std::mutex m;}; void transfer(bank_account& from, bank_account& to, int amount){if(&from ==&to)// avoid deadlock in case of self transferreturn; // lock both mutexes without deadlockstd::lock(from.m, to.m);// make sure both already-locked mutexes are unlocked at the end of scopestd::lock_guard lock1{from.m, std::adopt_lock};std::lock_guard lock2{to.m, std::adopt_lock}; // equivalent approach:// std::unique_lock<std::mutex> lock1{from.m, std::defer_lock};// std::unique_lock<std::mutex> lock2{to.m, std::defer_lock};// std::lock(lock1, lock2); from.balance-= amount; to.balance+= amount;} int main(){ bank_account my_account{100}; bank_account your_account{50}; std::thread t1{transfer, std::ref(my_account), std::ref(your_account), 10};std::thread t2{transfer, std::ref(your_account), std::ref(my_account), 5}; t1.join(); t2.join(); std::cout<<"my_account.balance = "<< my_account.balance<<"\n""your_account.balance = "<< your_account.balance<<'\n';}
Output:
my_account.balance = 95 your_account.balance = 55
[edit]See also
constructs a lock_guard , optionally locking the given mutex (public member function of std::lock_guard<Mutex> ) | |
constructs a unique_lock , optionally locking (i.e., taking ownership of) the supplied mutex (public member function of std::unique_lock<Mutex> ) |