15#include <system_error>
18#include <unordered_map>
40 std::string&& thread_name)
47 std::string ToString()
const
50 "'%s' in %s:%s%s (in thread '%s')",
54 std::string
Name()
const
68using LockStack = std::vector<LockStackItem>;
69using LockStacks = std::unordered_map<std::thread::id, LockStack>;
71using LockPair = std::pair<void*, void*>;
72using LockOrders = std::map<LockPair, LockStack>;
93 LogError(
"POTENTIAL DEADLOCK DETECTED");
94 LogError(
"Previous lock order was:");
121 tfm::format(std::cerr,
"Assertion failed: detected inconsistent lock order for %s, details in debug log.\n",
s2.back().second.ToString());
133 if (i.first == mutex) {
140 "Assertion failed: detected double lock for %s, details in debug log.\n",
144 throw std::logic_error(
"double lock detected");
147template <
typename MutexType>
151 std::is_base_of_v<RecursiveMutex, MutexType> ||
152 std::is_base_of_v<std::recursive_mutex, MutexType>;
155 std::lock_guard<std::mutex> lock(
lockdata.dd_mutex);
195 std::lock_guard<std::mutex> lock(
lockdata.dd_mutex);
200 lockdata.m_lock_stacks.erase(std::this_thread::get_id());
204template <
typename MutexType>
209template void EnterCritical(
const char*,
const char*,
int, std::mutex*,
bool);
210template void EnterCritical(
const char*,
const char*,
int, std::recursive_mutex*,
bool);
215 std::lock_guard<std::mutex> lock(
lockdata.dd_mutex);
226 LogError(
"INCONSISTENT LOCK ORDER DETECTED");
227 LogError(
"Current lock order (least recent first) is:");
229 LogError(
" %s", i.second.ToString());
232 tfm::format(std::cerr,
"%s:%s %s was not most recent critical section locked, details in debug log.\n", file, line,
guardname);
235 throw std::logic_error(
strprintf(
"%s was not most recent critical section locked",
guardname));
246 std::lock_guard<std::mutex> lock(
lockdata.dd_mutex);
251 result += i.
second.ToString() +
std::string(
"\n");
258 std::lock_guard<std::mutex> lock(
lockdata.dd_mutex);
262 if (i.first == mutex)
return true;
268template <
typename MutexType>
278template <
typename MutexType>
291 std::lock_guard<std::mutex> lock(
lockdata.dd_mutex);
293 LockOrders::iterator it =
lockdata.lockorders.lower_bound(
item);
294 while (it !=
lockdata.lockorders.end() && it->first.first ==
cs) {
295 const LockPair invitem = std::make_pair(it->first.second, it->first.first);
310 std::lock_guard<std::mutex> lock(
lockdata.dd_mutex);
311 const auto it =
lockdata.m_lock_stacks.find(std::this_thread::get_id());
312 if (it ==
lockdata.m_lock_stacks.end()) {
315 return it->second.empty();
std::string ThreadGetInternalName()
Get the thread's internal (in-memory) name; used e.g.
void AssertLockHeldInternal(const char *pszName, const char *pszFile, int nLine, MutexType *cs) EXCLUSIVE_LOCKS_REQUIRED(cs)
void EnterCritical(const char *pszName, const char *pszFile, int nLine, MutexType *cs, bool fTry=false)
void DeleteLock(void *cs)
void CheckLastCritical(void *cs, std::string &lockname, const char *guardname, const char *file, int line)
void AssertLockNotHeldInternal(const char *pszName, const char *pszFile, int nLine, MutexType *cs) LOCKS_EXCLUDED(cs)
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.