diff --git a/include/lockSet.h b/include/lockSet.h index d58e09d..9b46a73 100644 --- a/include/lockSet.h +++ b/include/lockSet.h @@ -76,7 +76,43 @@ public: * execute any fancy cleanup logic. It'll just clear() out the list. */ void registerInQutexQueues( - const std::shared_ptr &lockvoker); + 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; + } + + void 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); + } + } + /** * @brief Try to acquire all locks in order; back off if acquisition fails @@ -88,8 +124,53 @@ public: bool tryAcquireOrBackOff( LockerAndInvokerBase &lockvoker, std::optional> &firstFailedQutex - = std::nullopt); - void unregisterFromQutexQueues(); + = std::nullopt + ) + { + 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; + } // @brief Release all locks void release() diff --git a/smocore/CMakeLists.txt b/smocore/CMakeLists.txt index 09a1758..28397d5 100644 --- a/smocore/CMakeLists.txt +++ b/smocore/CMakeLists.txt @@ -11,7 +11,6 @@ add_library(smocore STATIC painfulQuale.cpp qutex.cpp lockerAndInvokerBase.cpp - lockSet.cpp serializedAsynchronousContinuation.cpp # Body diff --git a/smocore/lockSet.cpp b/smocore/lockSet.cpp deleted file mode 100644 index cb7ef15..0000000 --- a/smocore/lockSet.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#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