std::defer_...:adopt_lock(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

okay so bestie, welcome to the std::defer_...:adopt_lock(3) page from the C++ Standard Libary manual β€” yes, that's the spelling up top, and we're rolling with it πŸ’…

🌸 NAME 🌸

the name vibe is std::defer_lock,std::try_to_lock,std::adopt_lock β€” and it's literally repeated as std::defer_lock,std::try_to_lock,std::adopt_lock. these three are the lock-strategy tag girlies πŸ”₯

✨ Synopsis ✨

first things first: it's Defined in header <mutex> 🫢

          Defined in header <mutex>
          constexpr std::defer_lock_t defer_lock {};           (since C++11)
                                                               (until C++17)
          inline constexpr std::defer_lock_t defer_lock {};    (since C++17)
          constexpr std::try_to_lock_t try_to_lock {};         (since C++11)
                                                               (until C++17)
          inline constexpr std::try_to_lock_t try_to_lock {};  (since C++17)
          constexpr std::adopt_lock_t adopt_lock {};           (since C++11)
                                                               (until C++17)
          inline constexpr std::adopt_lock_t adopt_lock {};    (since C++17)

so std::defer_lock, std::try_to_lock and std::adopt_lock are instances of empty struct tag types std::defer_lock_t, std::try_to_lock_t and std::adopt_lock_t respectively β€” iconic, honestly ✨

they're used to specify locking strategies for std::lock_guard, std::unique_lock and std::shared_lock πŸŽ€

the type β†’ effect tea is:

  • 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 πŸ‘‘

🧸 Example 🧸

run this code, bestie β€” it's giving bank transfer example energy πŸ’Έ

        // 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 transfer
                return;

            // lock both mutexes without deadlock
            std::lock(from.m, to.m);
            // make sure both already-locked mutexes are unlocked at the end of
       scope
            std::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 πŸ’–

and the output ate, periodt:

my_account.balance = 95
your_account.balance = 55

πŸ‘€ See also πŸ‘€

the see-also girlies are:

  • defer_lock_t β€” tag type used to specify locking strategy (C++11) (class)
  • try_to_lock_t β€” tag type used to specify locking strategy (C++11) (class)
  • adopt_lock_t β€” tag type used to specify locking strategy (C++11) (class)
  • constructor β€” constructs a lock_guard, optionally locking the given mutex (public member function of std::lock_guard<Mutex>)
  • constructor β€” constructs a unique_lock, optionally locking (i.e., taking ownership of) the supplied mutex (public member function of std::unique_lock<Mutex>)

that's it, bestie 🫢 β€” source: http://cppreference.com, version/date: 2024.06.10, footer page: std::defer_...:adopt_lock(3). slay πŸ’…βœ¨

πŸ“¦ where this page comes from