LockSet: Move method impls into template header
This commit is contained in:
+84
-3
@@ -76,7 +76,43 @@ public:
|
|||||||
* execute any fancy cleanup logic. It'll just clear() out the list.
|
* execute any fancy cleanup logic. It'll just clear() out the list.
|
||||||
*/
|
*/
|
||||||
void registerInQutexQueues(
|
void registerInQutexQueues(
|
||||||
const std::shared_ptr<LockerAndInvokerBase> &lockvoker);
|
const std::shared_ptr<LockerAndInvokerBase> &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
|
* @brief Try to acquire all locks in order; back off if acquisition fails
|
||||||
@@ -88,8 +124,53 @@ public:
|
|||||||
bool tryAcquireOrBackOff(
|
bool tryAcquireOrBackOff(
|
||||||
LockerAndInvokerBase &lockvoker,
|
LockerAndInvokerBase &lockvoker,
|
||||||
std::optional<std::reference_wrapper<Qutex>> &firstFailedQutex
|
std::optional<std::reference_wrapper<Qutex>> &firstFailedQutex
|
||||||
= std::nullopt);
|
= std::nullopt
|
||||||
void unregisterFromQutexQueues();
|
)
|
||||||
|
{
|
||||||
|
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<int>(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
|
// @brief Release all locks
|
||||||
void release()
|
void release()
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ add_library(smocore STATIC
|
|||||||
painfulQuale.cpp
|
painfulQuale.cpp
|
||||||
qutex.cpp
|
qutex.cpp
|
||||||
lockerAndInvokerBase.cpp
|
lockerAndInvokerBase.cpp
|
||||||
lockSet.cpp
|
|
||||||
serializedAsynchronousContinuation.cpp
|
serializedAsynchronousContinuation.cpp
|
||||||
|
|
||||||
# Body
|
# Body
|
||||||
|
|||||||
@@ -1,100 +0,0 @@
|
|||||||
#include <lockSet.h>
|
|
||||||
#include <qutex.h>
|
|
||||||
|
|
||||||
namespace smo {
|
|
||||||
|
|
||||||
// Template method implementations that need full Qutex definition
|
|
||||||
// These will be explicitly instantiated for the types we need
|
|
||||||
|
|
||||||
template <class OriginalCbFnT>
|
|
||||||
void LockSet<OriginalCbFnT>::registerInQutexQueues(
|
|
||||||
const std::shared_ptr<LockerAndInvokerBase> &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 <class OriginalCbFnT>
|
|
||||||
bool LockSet<OriginalCbFnT>::tryAcquireOrBackOff(
|
|
||||||
LockerAndInvokerBase &lockvoker,
|
|
||||||
std::optional<std::reference_wrapper<Qutex>> &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<int>(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 <class OriginalCbFnT>
|
|
||||||
void LockSet<OriginalCbFnT>::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
|
|
||||||
Reference in New Issue
Block a user