From this post, I learned the following:
std::mutex
, and check if m_holder
equals to the current thread id. I think the way is kind of hack, since it is considered a bad idea to inherit from std class. Moreover, m_holder
is some implementation of some C++ library which is not a standard interfaceowns_lock
of unique_lock
. However, it is a bad idea, since the method only checks if the current lock holds the mutex. We don't use unique_lock
in this way.recursive_mutex
can save us from deadlock when we double lock a mutex in a thread. However, we must firstly check our code design before we decide that we really need to use this. However, I think I have a good design. What I need is a runtime check that if a certain mutex is locked twice by a thread, it will crash rather than dead lock. So a recursive_mutex
seems not suitable for me.There are ways to have your cake and eat it with the first solution.
We could achieve exactly the same result if we wrapped the std::mutex
as a member instead of inheriting from it:
class mutex
{
std::mutex m_mutex;
std::atomic<std::thread::id> m_holder = std::thread::id{};
public:
void lock()
{
// TODO: if we wanted to, we could check locked_by_caller()
// and panic if true
m_mutex.lock();
m_holder = std::this_thread::get_id();
}
bool try_lock()
{
if (m_mutex.try_lock()) {
m_holder = std::this_thread::get_id();
return true;
}
return false;
}
void unlock()
{
m_mutex.unlock();
}
bool locked_by_caller() const
{
return m_holder == std::this_thread::get_id();
}
};
Original code provided by @AmiTavory at https://stackoverflow.com/a/30109512/5740428
Moreover,
m_holder
is some implementation of some C++ library which is not a standard interface
No, you've misunderstood the original code. m_holder
is a member we defined ourselves. We're not relying on any particular standard library implementation. In general, standard library members are named something like _M_holder
to use reserved names which can't be replaced by macros.