Genau genommen ging es um die Überprüfung der Sperrung von std::mutex
direkt. Wenn es jedoch erlaubt ist, es in eine neue Klasse einzukapseln, ist es sehr einfach, dies zu tun:
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
};
Beachten Sie Folgendes:
- Im Freigabemodus hat dies keinen Overhead gegenüber
std::mutex
außer möglicherweise für Konstruktion/Zerstörung (was bei Mutex-Objekten kein Thema ist). - Die
m_holder
auf das Mitglied wird nur zugegriffen, wenn der Mutex genommen und freigegeben wird. Somit dient der Mutex selbst als Mutex vonm_holder
. Mit sehr schwachen Annahmen zum Typstd::thread::id
,locked_by_caller
wird korrekt funktionieren. - Andere STL-Komponenten, z. B.
std::lock_guard
sind Vorlagen, also funktionieren sie gut mit dieser neuen Klasse.
std::unique_lock<L>
hat owns_lock
Mitgliedsfunktion (entspricht is_locked
wie du sagst).
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
}
BEARBEITEN: In dieser Lösung sollten alle Sperroperationen über unique_lock glock
durchgeführt werden kein 'roher' Mutex gmtx
. Beispiel:alpha
Member-Funktion wird mit lock_guard<unique_lock<mutex>>
umgeschrieben (oder einfach lock_guard<decltype(glock)>
).
Sie könnten einfach einen recursive_mutex
verwenden , die mehrmals im selben Thread gesperrt werden können. Hinweis:Wenn es mein Code wäre, würde ich ihn so umstrukturieren, dass ich keinen recursive_mutex
benötige , aber es wird Ihr Problem lösen.