How to implement class lock objects for multi-threaded access

Assuming I have the following simplified class and you want to protect the resource from multi-threaded access. How can I include sth as a class lock, where each "entry point" to the public interface must first obtain a class lock before allowing the interface to be used?

class MyClass
{
  public:
    void A();
    void B();
    void C();
    void D();
    void E();

  private:
    SharedResource _res;
}

void MyClass::A()
{
  B();
  C();
  D();
  E();
}

void MyClass::B()
{
  // do sth with _res
}

void MyClass::C()
{
  // do sth with _res
}

void MyClass::D()
{
  // do sth with _res
}

void MyClass::E()
{
  // do sth with _res
}

I could do this by locking the class mutex in each of the methods, and then apply two versions of the BE methods:

void MyClass::A()
{
  std::lock<std::mutex> lock(_mutex);
  B_mtx();
  C_mtx();
  D_mtx();
  E_mtx();
}

void MyClass::B()
{
  std::lock<std::mutex> lock(_mutex);
  B_mtx();
}

void MyClass::B_mtx()
{
  // logic of B
}

// ...

, , , . ? getLock, move-assigment, ? , ?

+4
1

, , std::lock ( , , ):

class MyClass
{
  mutable std::mutex mtx;

public:
  using Lock = std::unique_lock<std::mutex>;

  void A(Lock &l)
  {
    assert(l.mutex() == mtx);
    // ...
  }

  void B(Lock &l)
  {
    assert(l.mutex() == mtx);
    // ...
  }

  Lock getLock() const
  { return Lock(mtx); }

  void releaseLock(Lock &&l) const
  { Lock l2 = std::move(l); }
};

- . ​​ (1):

class MyClass
{
public:
  void A()
  {
    //...
  }

  void B()
  {
    //...
  }
};

class MyClass_ThreadSafe
{
  MyClass m;
  std::mutex mtx;

public:
  template <class Operation>
  auto call(Operation o) -> decltype(o(m))
  {
    std::unique_lock l(mtx);
    return o(m);
  }
};

// Usage:

MyClass_ThreadSafe mc;
mc.call(
  [](MyClass &c)
  {
    c.A();
    c.B();
  }
);

(1)++ Beyond 2012 — Herb Sutter: ++ Concurrency 36 .

+2

Source: https://habr.com/ru/post/1617249/


All Articles