#include #include namespace smo { // Template method implementations that need full Qutex definition // These will be explicitly instantiated for the types we need template void LockSet::registerInQutexQueues( const std::shared_ptr &lockvoker ) { /** EXPLANATION: * Register the lockvoker with each Qutex and store the returned * iterator to its place within each Qutex's queue. We store the * iterator so that we can quickly move the lockvoker around within * the queue, and eventually, erase() it when we acquire all the * locks. */ for (auto& lockUsageDesc : locks) { lockUsageDesc.second = lockUsageDesc.first.get().registerInQueue( lockvoker); } registeredInQutexQueues = true; } template bool LockSet::tryAcquireOrBackOff( LockerAndInvokerBase &lockvoker, std::optional> &firstFailedQutex ) { if (!registeredInQutexQueues) { throw std::runtime_error( std::string(__func__) + ": LockSet::tryAcquireOrBackOff() called but not registered in " "Qutex queues"); } if (allLocksAcquired) { throw std::runtime_error( std::string(__func__) + ": LockSet::tryAcquireOrBackOff() called but allLocksAcquired " "is already true"); } // Try to acquire all required locks int nAcquired = 0; const int nRequiredLocks = static_cast(locks.size()); for (auto& lockUsageDesc : locks) { if (!lockUsageDesc.first.get().tryAcquire( lockvoker, nRequiredLocks)) { // Set the first failed qutex for debugging firstFailedQutex = std::ref(lockUsageDesc.first.get()); break; } nAcquired++; } if (nAcquired < nRequiredLocks) { // Release any locks we managed to acquire for (int i = 0; i < nAcquired; i++) { locks[i].first.get().backoff(lockvoker, nRequiredLocks); } return false; } allLocksAcquired = true; return true; } template void LockSet::unregisterFromQutexQueues() { if (!registeredInQutexQueues) { throw std::runtime_error( std::string(__func__) + ": LockSet::unregisterFromQutexQueues() called but not " "registered in Qutex queues"); } // Unregister from all qutex queues for (auto& lockUsageDesc : locks) { auto it = lockUsageDesc.second; lockUsageDesc.first.get().unregisterFromQueue(it); } } } // namespace smo