开发者

Why there is no scoped locks for multiple mutexes in C++0x or Boost.Thread?

开发者 https://www.devze.com 2022-12-28 16:12 出处:网络
C++0x thread library or Boost.thread define non-member variadic template function that lock all lock avoiding dead lock.

C++0x thread library or Boost.thread define non-member variadic template function that lock all lock avoiding dead lock.

template <class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);

While this function avoid help to deadlock, the standard do not includes the associated scoped lock 开发者_如何学运维to write exception safe code.

{
  std::lock(l1,l2);
  // do some thing
  // unlock li l2 exception safe
}

That means that we need to use other mechanism as try-catch block to make exception safe code or define our own scoped lock on multiple mutexes ourselves or even do that

{
  std::lock(l1,l2);
  std::unique_lock lk1(l1, std::adopted);
  std::unique_lock lk2(l2, std::adopted);
  // do some thing
  // unlock li l2 on destruction of lk1 lk2
}

Why the standard doesn't includes a scoped lock on multiple mutexes of the same type, as for example

{
  std::array_unique_lock<std::mutex> lk(l1,l2);
  // do some thing
  // unlock l1 l2 on destruction of lk
}

or tuples of mutexes

{
  std::tuple_unique_lock<std::mutex, std::recursive_mutex> lk(l1,l2);
  // do some thing
  // unlock l1 l2 on destruction of lk
}

Is there something wrong on the design?


Updated: description from the standard

template <class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);

Requires: Each template parameter type shall meet the Mutex requirements, except that a call to try_- lock() may throw an exception. [ Note: The unique_lock class template meets these requirements when suitably instantiated. —end note ]

Effects: All arguments are locked via a sequence of calls to lock(), try_lock(), or unlock() on each argument. The sequence of calls shall not result in deadlock, but is otherwise unspecified. [ Note: A deadlock avoidance algorithm such as try-and-back-off must be used, but the specific algorithm is not specified to avoid over-constraining implementations. —end note ] If a call to lock() or try_lock() throws an exception, unlock() shall be called for any argument that had been locked by a call to lock() or try_lock().


I have accept the answer. I understand that the main reason is because there is no enough time to make the C++0x Thread library better. I hope that TR2 will include much more things.


I think that by providing defer_lock_t (and adopt_lock_t) the expectation is that usage will be like your second example, or probably more like:

 std::unqiue_lock ul1(l1, std::deferred);
 std::unique_lock ul2(l2, std::deferred);
 std::lock(ul1, ul2);

This is exception safe and all that good stuff.

I certainly can't pretend to know the minds of the designers, but my guess is they are making an effort to provide a minimal set of portable, safe, primitives. A scoped multiple lock type is just so much icing, and it's icing that if in the standard needs to be specified and designed, or in boost.thread, icing that needs to be implemented (and of course ultimately the standard has to be concerned about implementation too, look what happened with export).


Constructing one object that locks multiple locks does not avoid any deadlocks any more than locking them individually. You can't lock two locks simultaneously.. unless you use two threads, which kind of defeats the point. This holds true even if you put them in the same statement.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号