The cppreference page for std::recursive_mutex says:
The maximum number of times that a recursive_mutex may be locked is unspecified, but after that number is reached, calls to lock will throw std::system_error and calls to try_lock will return false.
So:
If I take this literally, I have to conclude that it's unsafe to use (lock) a std::recursive_mutex at all, since that maximum may be zero.
But, maybe that interpretation is too silly, and I should assume it means the maximum is always at least 1, and may be exactly 1?
Ok, in that case, it's safe to use std::recursive_mutex like std::mutex, but it's unsafe to ever use it recursively (i.e. lock it twice simultaneously), since the maximum may be 1.
But, maybe that interpretation is still too silly, and I should assume it means the maximum is always at least 2, and may be exactly 2? Ok, in that case I can lock it twice, but it's unsafe to lock it 3 times.
The reasoning above seems increasingly tenous, which seems to lead to the conclusion "std::recursive_mutex doesn't have a clear contract, so it's unsafe to use it, period". I.e. if I want a reliable recursive mutex, I have to write my own.
(Attempting to handle the std::system_error doesn't seem like a realistic alternative, since it would be simpler to just write an alternative recursive mutex implementation from scratch, and not use std::recursive_mutex at all.)
This seems a shame, since std::recursive_mutex might, in reality, be a high-quality implementation whose maximum is hundreds, or thousands, or billions (maybe 231-1), or quintillions (maybe 263-1), any of which would be useful if it could be relied on.
Is there any safe/reliable way to use std::recursive_mutex ?
The standard does not specify the number, but I think it is reasonable to assume that it is a reasonable number.
For 32 bits processors I would expect it to be a 32 bit recursion (approx 4Billion) - that would not be achievable, as the stack used by 4 billion calls would consume all the memory of the processor.
For 64 bit machines, either 32 or 64 bits would be reasonable.
Algorithmically the recursive use of a mutex is problematic - if you think the potential recursions are > the number of bits on the processor (32 recursions / 64 recursions), then you probably need an alternative design - where the lock is held more globally and not used in inner functions.
The unspecified nature, allows the standard to be flexible, yet deliver something useful. If they specified a minimum size, that may limit the ability to implement C++ on some processors, due to the counter would need to be some form of atomic operation to work successfully.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With