Title
Generic try_lock contradiction
Status
c++11
Section
[thread.lock.algorithm]
Submitter
Chris Fairles

Created on 2009-02-14.00:00:00 last changed 162 months ago

Messages

Date: 2010-10-21.18:28:33

Proposed resolution:

Change [thread.lock.algorithm], p2:

-2- Effects: Calls try_lock() for each argument in order beginning with the first until all arguments have been processed or a call to try_lock() fails, either by returning false or by throwing an exception. If a call to try_lock() fails, unlock() shall be called for all prior arguments and there shall be no further calls to try_lock().

Delete the note from [thread.lock.algorithm], p3

-3- Returns: -1 if all calls to try_lock() returned true, otherwise a 0-based index value that indicates the argument for which try_lock() returned false. [Note: On return, either all arguments will be locked or none will be locked. -- end note]

Date: 2010-10-21.18:28:33

[ Batavia (2009-05): ]

We agree with the proposed resolution. Move to Tentatively Ready.

Date: 2010-10-21.18:28:33

[ Summit: ]

Move to review. Agree with proposed resolution.

Date: 2009-02-14.00:00:00

In [thread.lock.algorithm], the generic try_lock effects (p2) say that a failed try_lock is when it either returns false or throws an exception. In the event a call to try_lock does fail, by either returning false or throwing an exception, it states that unlock shall be called for all prior arguments. Then the returns clause (p3) goes on to state in a note that after returning, either all locks are locked or none will be. So what happens if multiple locks fail on try_lock?

Example:

#include <mutex>

int main() {
 std::mutex m0, m1, m2;
 std::unique_lock<std::mutex> l0(m0, std::defer_lock);
 std::unique_lock<std::mutex> l1(m1); //throws on try_lock
 std::unique_lock<std::mutex> l2(m2); //throws on try_lock

 int result = std::try_lock(l0, l1, l2);

 assert( !l0.owns_lock() );
 assert( l1.owns_lock() ); //??
 assert( l2.owns_lock() ); //??
}

The first lock's try_lock succeeded but, being a prior argument to a lock whose try_lock failed, it gets unlocked as per the effects clause of [thread.lock.algorithm]. However, 2 locks remain locked in this case but the return clause states that either all arguments shall be locked or none will be. This seems to be a contradiction unless the intent is for implementations to make an effort to unlock not only prior arguments, but the one that failed and those that come after as well. Shouldn't the note only apply to the arguments that were successfully locked?

Further discussion and possible resolutions in c++std-lib-23049.

History
Date User Action Args
2011-08-23 20:07:26adminsetstatus: wp -> c++11
2010-10-21 18:28:33adminsetmessages: + msg4688
2010-10-21 18:28:33adminsetmessages: + msg4687
2010-10-21 18:28:33adminsetmessages: + msg4686
2009-02-14 00:00:00admincreate