Created on 2024-11-13.00:00:00 last changed 2 days ago
Proposed resolution:
This wording is relative to N4993.
Drafting Note: I've chosen to use the move-into-temporary-and-swap idiom here to keep things short and sweet. Since move construction, swap, and destruction are all `noexcept`, I've promoted move assignment from "Throws: Nothing" to `noexcept` as well. This is consistent with eliminating the implicit narrow contract condition that `*this` and `u` refer to distinct objects.
In the class synopsis in [thread.lock.unique.general], annotate the move assignment operator as `noexcept`:
namespace std { template<class Mutex> class unique_lock { [...] unique_lock& operator=(unique_lock&& u) noexcept; [...] }; }
Modify [thread.lock.unique.cons] as follows:
unique_lock& operator=(unique_lock&& u) noexcept;
-18- Effects:
If `owns` calls `pm->unlock()`.Equivalent to: `unique_lock{std::move(u)}.swap(*this)`.-?- Returns: `*this`.
-19- Postconditions: `pm == u_p.pm` and `owns == u_p.owns` (where `u_p` is the state of `u` just prior to this construction), `u.pm == 0` and `u.owns == false`.
-20- [Note 1: With a recursive mutex it is possible for both `*this` and u to own the same mutex before the assignment. In this case, *this will own the mutex after the assignment and u will not. — end note]
-21- Throws: Nothing.
Modify [thread.lock.shared.cons] as follows:
shared_lock& operator=(shared_lock&& sl) noexcept;
-17- Effects:
If `owns` calls `pm->unlock_shared()`.Equivalent to: `shared_lock{std::move(sl)}.swap(*this)`.-?- Returns: `*this`.
-18- Postconditions: `pm == sl_p.pm` and `owns == sl_p.owns` (where `sl_p` is the state of `sl` just prior to this assignment), `sl.pm == nullptr` and `sl.owns == false`.
[ 2024-11-18; Casey expands the PR to cover `shared_lock` ]
`shared_lock` has the same problems, and can be fixed in the same way.
The postconditions in [thread.lock.unique.cons] paragraph 19:
Postconditions: `pm == u_p.pm` and `owns == u_p.owns` (where `u_p` is the state of `u` just prior to this construction), `u.pm == 0` and `u.owns == false`.contradict themselves if `*this` and the parameter `u` refer to the same object. (Presumably "this construction" means the assignment, and it is copy-pasta from the move constructor postconditions.) Apparently `unique_lock` didn't get the memo that we require well-defined behavior from self-move-assignment as of LWG 2839.
Also, the move assignment operator doesn't specify what it returns.
History | |||
---|---|---|---|
Date | User | Action | Args |
2024-11-18 13:26:33 | admin | set | messages: + msg14456 |
2024-11-13 21:15:00 | admin | set | messages: + msg14454 |
2024-11-13 00:00:00 | admin | create |