Qutex: currOwner should use registered sh_ptr to Lockvoker
This ensures that the Lockvoker object we access from currOwner remains valid past the lifetime of the Lockvoker object that gets copied and invoked by boost::asio
This commit is contained in:
@@ -68,7 +68,7 @@ public:
|
|||||||
|
|
||||||
// Implement the virtual method from AsynchronousContinuationChainLink
|
// Implement the virtual method from AsynchronousContinuationChainLink
|
||||||
virtual std::shared_ptr<AsynchronousContinuationChainLink>
|
virtual std::shared_ptr<AsynchronousContinuationChainLink>
|
||||||
getCallersContinuation() override
|
getCallersContinuationShPtr() override
|
||||||
{ return originalCallback.callerContinuation; }
|
{ return originalCallback.callerContinuation; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public:
|
|||||||
virtual ~AsynchronousContinuationChainLink() = default;
|
virtual ~AsynchronousContinuationChainLink() = default;
|
||||||
|
|
||||||
virtual std::shared_ptr<AsynchronousContinuationChainLink>
|
virtual std::shared_ptr<AsynchronousContinuationChainLink>
|
||||||
getCallersContinuation() = 0;
|
getCallersContinuationShPtr() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace smo
|
} // namespace smo
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public:
|
|||||||
* @param qutex The Qutex to get the iterator for
|
* @param qutex The Qutex to get the iterator for
|
||||||
* @return Iterator pointing to this lockvoker in the Qutex's queue
|
* @return Iterator pointing to this lockvoker in the Qutex's queue
|
||||||
*/
|
*/
|
||||||
virtual List::iterator getLockvokerIteratorForQutex(Qutex& qutex) = 0;
|
virtual List::iterator getLockvokerIteratorForQutex(Qutex& qutex) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Awaken this lockvoker by posting it to its io_service
|
* @brief Awaken this lockvoker by posting it to its io_service
|
||||||
|
|||||||
+3
-2
@@ -90,13 +90,14 @@ public:
|
|||||||
void release();
|
void release();
|
||||||
|
|
||||||
#ifdef CONFIG_ENABLE_DEBUG_LOCKS
|
#ifdef CONFIG_ENABLE_DEBUG_LOCKS
|
||||||
LockerAndInvokerBase* getCurrOwner() const { return currOwner; }
|
std::shared_ptr<LockerAndInvokerBase> getCurrOwner() const
|
||||||
|
{ return currOwner; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#ifdef CONFIG_ENABLE_DEBUG_LOCKS
|
#ifdef CONFIG_ENABLE_DEBUG_LOCKS
|
||||||
std::string name;
|
std::string name;
|
||||||
LockerAndInvokerBase* currOwner;
|
std::shared_ptr<LockerAndInvokerBase> currOwner;
|
||||||
#endif
|
#endif
|
||||||
SpinLock lock;
|
SpinLock lock;
|
||||||
LockerAndInvokerBase::List queue;
|
LockerAndInvokerBase::List queue;
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ public:
|
|||||||
* @return Iterator pointing to this lockvoker in the Qutex's queue
|
* @return Iterator pointing to this lockvoker in the Qutex's queue
|
||||||
*/
|
*/
|
||||||
LockerAndInvokerBase::List::iterator
|
LockerAndInvokerBase::List::iterator
|
||||||
getLockvokerIteratorForQutex(Qutex& qutex) override
|
getLockvokerIteratorForQutex(Qutex& qutex) const override
|
||||||
{
|
{
|
||||||
return serializedContinuation.requiredLocks.getLockUsageDesc(
|
return serializedContinuation.requiredLocks.getLockUsageDesc(
|
||||||
qutex).second;
|
qutex).second;
|
||||||
|
|||||||
+7
-3
@@ -44,7 +44,9 @@ bool Qutex::tryAcquire(
|
|||||||
{
|
{
|
||||||
isOwned = true;
|
isOwned = true;
|
||||||
#ifdef CONFIG_ENABLE_DEBUG_LOCKS
|
#ifdef CONFIG_ENABLE_DEBUG_LOCKS
|
||||||
currOwner = const_cast<LockerAndInvokerBase*>(&tryingLockvoker);
|
// Use the stored iterator from the LockSet
|
||||||
|
auto it = tryingLockvoker.getLockvokerIteratorForQutex(*this);
|
||||||
|
currOwner = *it;
|
||||||
#endif
|
#endif
|
||||||
lock.release();
|
lock.release();
|
||||||
return true;
|
return true;
|
||||||
@@ -59,7 +61,7 @@ bool Qutex::tryAcquire(
|
|||||||
{
|
{
|
||||||
isOwned = true;
|
isOwned = true;
|
||||||
#ifdef CONFIG_ENABLE_DEBUG_LOCKS
|
#ifdef CONFIG_ENABLE_DEBUG_LOCKS
|
||||||
currOwner = const_cast<LockerAndInvokerBase*>(&tryingLockvoker);
|
currOwner = queue.front();
|
||||||
#endif
|
#endif
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
@@ -96,7 +98,9 @@ bool Qutex::tryAcquire(
|
|||||||
// Not found in rear portion - must be in top X%, so succeed
|
// Not found in rear portion - must be in top X%, so succeed
|
||||||
isOwned = true;
|
isOwned = true;
|
||||||
#ifdef CONFIG_ENABLE_DEBUG_LOCKS
|
#ifdef CONFIG_ENABLE_DEBUG_LOCKS
|
||||||
currOwner = const_cast<LockerAndInvokerBase*>(&tryingLockvoker);
|
// Use the stored iterator from the LockSet
|
||||||
|
auto it = tryingLockvoker.getLockvokerIteratorForQutex(*this);
|
||||||
|
currOwner = *it;
|
||||||
#endif
|
#endif
|
||||||
lock.release();
|
lock.release();
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ SerializedAsynchronousContinuation<OriginalCbFnT>
|
|||||||
* lockvoker.
|
* lockvoker.
|
||||||
*/
|
*/
|
||||||
for (std::shared_ptr<AsynchronousContinuationChainLink> currContin =
|
for (std::shared_ptr<AsynchronousContinuationChainLink> currContin =
|
||||||
this->serializedContinuation.getCallersContinuation();
|
this->serializedContinuation.getCallersContinuationShPtr();
|
||||||
currContin != nullptr;
|
currContin != nullptr;
|
||||||
currContin = currContin->getCallersContinuation())
|
currContin = currContin->getCallersContinuationShPtr())
|
||||||
{
|
{
|
||||||
auto serializedCont = std::dynamic_pointer_cast<
|
auto serializedCont = std::dynamic_pointer_cast<
|
||||||
SerializedAsynchronousContinuation<OriginalCbFnT>>(currContin);
|
SerializedAsynchronousContinuation<OriginalCbFnT>>(currContin);
|
||||||
@@ -94,13 +94,14 @@ SerializedAsynchronousContinuation<OriginalCbFnT>
|
|||||||
* Hence, we have a gridlock.
|
* Hence, we have a gridlock.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
LockerAndInvokerBase* foreignOwnerPtr = firstFailedQutex.getCurrOwner();
|
std::shared_ptr<LockerAndInvokerBase> foreignOwnerShPtr =
|
||||||
|
firstFailedQutex.getCurrOwner();
|
||||||
// If no current owner, can't be a gridlock
|
// If no current owner, can't be a gridlock
|
||||||
if (foreignOwnerPtr == nullptr)
|
if (foreignOwnerShPtr == nullptr)
|
||||||
{ return false; }
|
{ return false; }
|
||||||
|
|
||||||
// Use reference for the rest of the function for safety.
|
// Use reference for the rest of the function for safety.
|
||||||
LockerAndInvokerBase& foreignOwner = *foreignOwnerPtr;
|
LockerAndInvokerBase &foreignOwner = *foreignOwnerShPtr;
|
||||||
|
|
||||||
/* For each lock in the foreign owner's LockSet, check if we hold it
|
/* For each lock in the foreign owner's LockSet, check if we hold it
|
||||||
* in any of our previous continuations (excluding our most immediate one)
|
* in any of our previous continuations (excluding our most immediate one)
|
||||||
@@ -128,9 +129,9 @@ SerializedAsynchronousContinuation<OriginalCbFnT>
|
|||||||
* should eventually be able to acquire that lock.
|
* should eventually be able to acquire that lock.
|
||||||
*/
|
*/
|
||||||
for (std::shared_ptr<AsynchronousContinuationChainLink> currContin =
|
for (std::shared_ptr<AsynchronousContinuationChainLink> currContin =
|
||||||
this->serializedContinuation.getCallersContinuation();
|
this->serializedContinuation.getCallersContinuationShPtr();
|
||||||
currContin != nullptr;
|
currContin != nullptr;
|
||||||
currContin = currContin->getCallersContinuation())
|
currContin = currContin->getCallersContinuationShPtr())
|
||||||
{
|
{
|
||||||
auto serializedCont = std::dynamic_pointer_cast<
|
auto serializedCont = std::dynamic_pointer_cast<
|
||||||
SerializedAsynchronousContinuation<OriginalCbFnT>>(currContin);
|
SerializedAsynchronousContinuation<OriginalCbFnT>>(currContin);
|
||||||
|
|||||||
Reference in New Issue
Block a user