A rigor di termini, la domanda riguardava il controllo del blocco di std::mutex direttamente. Tuttavia, se è consentito incapsularlo in una nuova classe, è molto semplice farlo:
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
};
Nota quanto segue:
- Nella modalità di rilascio, questo ha un sovraccarico pari a zero rispetto a
std::mutextranne possibilmente per la costruzione/distruzione (che non è un problema per gli oggetti mutex). - Il
m_holdermembro è accessibile solo tra l'acquisizione del mutex e il suo rilascio. Così il mutex stesso funge da mutex dim_holder. Con ipotesi molto deboli sul tipostd::thread::id,locked_by_callerfunzionerà correttamente. - Altri componenti STL, ad esempio
std::lock_guardsono modelli, quindi funzionano bene con questa nuova classe.
std::unique_lock<L> ha owns_lock funzione membro (equivalente di is_locked come dici tu).
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
}
MODIFICA: In questa soluzione, tutte le operazioni di blocco dovrebbero essere eseguite tramite unique_lock glock mutex non 'raw' gmtx . Ad esempio, alpha la funzione membro viene riscritta con lock_guard<unique_lock<mutex>> (o semplicemente lock_guard<decltype(glock)> ).
Potresti semplicemente usare un recursive_mutex , che può essere bloccato più volte sullo stesso thread. Nota:se fosse il mio codice, lo ristrutturerei in modo da non aver bisogno di un recursive_mutex , ma risolverà il tuo problema.