17 Ağustos 2018 Cuma

std::lock metodu

Giriş
Birden fazla mutex'i aynı anda kilitlemek için kullanırız.

İmzası şöyle
void lock( Lockable1& lock1, Lockable2& lock2, LockableN&... lockn );
Bir şekilde deadlock tespibit yapabiliyor.

Örnek
Aynı anda iki nesneyi kilitlemek için şöyle bir örnek verilebilir. Eğer bir nesneyi diğer nesneye atamak istersek assignment operator içinde her iki nesneyi de aynı anda kilitlemek gerekir. Bu durumda std::lock() metodunu kullanırız.

unique_lock ile şöyle yaparız. İlk iki satır scope'tan çıkarken mutex'lerin bırakılmasını sağlar.
std::unique_lock<std::mutex> lk1(mutex1, std::defer_lock);
std::unique_lock<std::mutex> lk2(mutex2, std::defer_lock);
std::lock(lk1, lk2);
Örnek
Şöyle yaparız. std::lock() ile kilitledikten sonra std::lock_guard<> ile mutex'ler bırakılır.
void transfer(bank_account &from, bank_account &to, int amount)
{
  // 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<std::mutex> lock1(from.m, std::adopt_lock);
  std::lock_guard<std::mutex> lock2(to.m, std::adopt_lock);
  
  from.balance -= amount;
  to.balance += amount;
}

Diğer

Timeout metodu
std::lock için timeout'lu bir metod yok. Ancak yazması kolay.
#include <mutex>
#include <chrono>

template <class Clock, class  Duration, class L0, class L1>
int
try_lock_until(std::chrono::time_point<Clock, Duration> t, L0& l0, L1& l1)
{
    std::unique_lock<L0> u0(l0, t);
    if (u0.owns_lock())
    {
        if (l1.try_lock_until(t) == 0) //Bu kısmı değiştirdim
        {
            u0.release();
            return -1;
        }
        else
            return 1;
    }
    return 0;
}

template <class Rep, class  Period, class L0, class L1>
int
try_lock_for(std::chrono::duration<Rep, Period> d, L0& l0, L1& l1)
{
    return try_lock_until(std::chrono::steady_clock::now() + d, l0, l1);
}


int main()
{
    std::timed_mutex  m1, m2;
    try_lock_for(std::chrono::milliseconds(50), m1, m2);
}



Hiç yorum yok:

Yorum Gönder