Estrictamente hablando, la pregunta era sobre verificar el bloqueo de std::mutex
directamente. Sin embargo, si se permite encapsularlo en una nueva clase, es muy fácil hacerlo:
class mutex :
public std::mutex
{
public:
#ifndef NDEBUG
void lock()
{
std::mutex::lock();
m_holder = std::this_thread::get_id();
}
#endif // #ifndef NDEBUG
#ifndef NDEBUG
void unlock()
{
m_holder = std::thread::id();
std::mutex::unlock();
}
#endif // #ifndef NDEBUG
#ifndef NDEBUG
/**
* @return true iff the mutex is locked by the caller of this method. */
bool locked_by_caller() const
{
return m_holder == std::this_thread::get_id();
}
#endif // #ifndef NDEBUG
private:
#ifndef NDEBUG
std::atomic<std::thread::id> m_holder;
#endif // #ifndef NDEBUG
};
Tenga en cuenta lo siguiente:
- En el modo de lanzamiento, esto tiene una sobrecarga cero sobre
std::mutex
excepto posiblemente para construcción/destrucción (que no es un problema para objetos mutex). - El
m_holder
solo se accede al miembro entre tomar el mutex y liberarlo. Por lo tanto, el mutex en sí mismo sirve como mutex dem_holder
. Con suposiciones muy débiles sobre el tipostd::thread::id
,locked_by_caller
funcionará correctamente. - Otros componentes STL, por ejemplo,
std::lock_guard
son plantillas, por lo que funcionan bien con esta nueva clase.
std::unique_lock<L>
tiene owns_lock
función miembro (equivalente a is_locked
como dices).
std::mutex gmtx;
std::unique_lock<std::mutex> glock(gmtx, std::defer_lock);
void alpha(void) {
std::lock_guard<decltype(glock)> g(glock);
beta(void);
// some other work
}
void beta(void) {
assert(glock.owns_lock()); // or just assert(glock);
// some real work
}
EDITAR: En esta solución, todas las operaciones de bloqueo deben realizarse a través de unique_lock glock
no mutex 'en bruto' gmtx
. Por ejemplo, alpha
la función miembro se reescribe con lock_guard<unique_lock<mutex>>
(o simplemente lock_guard<decltype(glock)>
).
Podrías usar un recursive_mutex
, que se puede bloquear varias veces en el mismo subproceso. Nota:si fuera mi código, lo reestructuraría para no necesitar un recursive_mutex
, pero solucionará su problema.