Reputation: 737
The std::unique_lock
has a couple of constructors accepting a xxx_lock_t
. These are empty structures:
struct adopt_lock_t {};
struct defer_lock_t {};
struct try_to_lock_t {};
And they are correspond to values as follows.
constexpr adopt_lock_t adopt_lock {};
constexpr defer_lock_t defer_lock {};
constexpr try_to_lock_t try_to_lock {};
Finally, here are std::unique_lock
's constructors.
unique_lock (mutex_type& m, adopt_lock_t tag);
unique_lock (mutex_type& m, defer_lock_t tag) noexcept;
unique_lock (mutex_type& m, try_to_lock_t tag);
My question is:
Why they use this kind of tags instead of an enum type?
I think by using an enum we don't need to declare constructors per each type of locking. I also agree that by implementing each type's constructor, it doesn't need to compare which lock type is give in the implementation.
What are the main reasons?
Upvotes: 5
Views: 680
Reputation: 170084
I also agree that by implementing each type's constructor, it doesn't need to compare which lock type is give in the implementation
But do you understand what that means? The c'tor will only ever do one type of locking, with either approach. But If the branching is in the c'tor, everybody pays for it. Even those who know in advance what branch they'll take. C++ is all about not paying for overhead you don't require. Implementing it like this allows for the following:
If you know in advance how you'll be locking, you don't pay for any branching.
If you don't know in advance, you can easily branch yourself. It will require default constructing of the lock, and (move) assigning to it. But those two operations will be fairly cheap anyway. It won't be too much added cost to the branch itself.
Upvotes: 2
Reputation: 7591
If you used enum
, you had to determine at runtime which mode to chose when locking, à la:
if(mode == lock::adopt_lock) {
...
} else if(mode == lock::defer_lock) {
...
}
else ...
With overloads, you move this distinction to compile-time.
Upvotes: 5