Sebenarnya, pertanyaannya adalah tentang memeriksa penguncian std::mutex
secara langsung. Namun, jika mengenkapsulasinya di kelas baru diperbolehkan, sangat mudah melakukannya:
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
};
Perhatikan hal berikut:
- Dalam mode rilis, ini memiliki overhead nol di atas
std::mutex
kecuali mungkin untuk konstruksi/penghancuran (yang bukan masalah untuk objek mutex). m_holder
anggota hanya diakses antara mengambil mutex dan melepaskannya. Jadi mutex itu sendiri berfungsi sebagai mutex darim_holder
. Dengan asumsi yang sangat lemah pada tipestd::thread::id
,locked_by_caller
akan bekerja dengan benar.- Komponen STL lainnya, mis.,
std::lock_guard
adalah template, sehingga berfungsi baik dengan kelas baru ini.
std::unique_lock<L>
memiliki owns_lock
fungsi anggota (setara dengan is_locked
seperti yang Anda katakan).
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
}
EDIT: Dalam solusi ini, semua operasi kunci harus dilakukan melalui unique_lock glock
bukan mutex 'mentah' gmtx
. Misalnya, alpha
fungsi anggota ditulis ulang dengan lock_guard<unique_lock<mutex>>
(atau cukup lock_guard<decltype(glock)>
).
Anda bisa menggunakan recursive_mutex
, yang dapat dikunci beberapa kali di utas yang sama. Catatan:Jika itu adalah kode saya, saya akan menyusun ulang sehingga saya tidak memerlukan recursive_mutex
, tetapi itu akan mengatasi masalah Anda.