Async: add sh_ptr<ContinuationChainLink> to Callback<>

This change enables us to finally implement the tracing of
continuations backward from the point of acquisition for deadlock
debugging.
This commit is contained in:
2025-09-27 18:30:09 -04:00
parent 2212aec080
commit 782bcd4567
26 changed files with 384 additions and 269 deletions
+18 -11
View File
@@ -6,6 +6,8 @@
#include <exception>
#include <componentThread.h>
#include <lockSet.h>
#include <callback.h>
#include <asynchronousContinuationChainLink.h>
namespace smo {
@@ -21,10 +23,11 @@ namespace smo {
*/
template <class OriginalCbFnT>
class AsynchronousContinuation
: public AsynchronousContinuationChainLink
{
public:
explicit AsynchronousContinuation(OriginalCbFnT originalCbFn)
: originalCbFn(std::move(originalCbFn))
explicit AsynchronousContinuation(Callback<OriginalCbFnT> originalCb)
: originalCallback(std::move(originalCb))
{}
/** EXPLANATION:
@@ -65,7 +68,7 @@ public:
}
public:
OriginalCbFnT originalCbFn;
Callback<OriginalCbFnT> originalCallback;
std::exception_ptr exception;
};
@@ -84,8 +87,9 @@ class NonPostedAsynchronousContinuation
: public AsynchronousContinuation<OriginalCbFnT>
{
public:
explicit NonPostedAsynchronousContinuation(OriginalCbFnT originalCbFn)
: AsynchronousContinuation<OriginalCbFnT>(originalCbFn)
explicit NonPostedAsynchronousContinuation(
Callback<OriginalCbFnT> originalCb)
: AsynchronousContinuation<OriginalCbFnT>(originalCb)
{}
/**
@@ -100,10 +104,11 @@ public:
template<typename... Args>
void callOriginalCb(Args&&... args)
{
if (AsynchronousContinuation<OriginalCbFnT>::originalCbFn)
if (AsynchronousContinuation<OriginalCbFnT>::originalCallback
.callbackFn)
{
AsynchronousContinuation<OriginalCbFnT>::originalCbFn(
std::forward<Args>(args)...);
AsynchronousContinuation<OriginalCbFnT>::originalCallback
.callbackFn(std::forward<Args>(args)...);
}
}
};
@@ -115,7 +120,7 @@ class PostedAsynchronousContinuation
public:
PostedAsynchronousContinuation(
const std::shared_ptr<ComponentThread> &caller,
OriginalCbFnT originalCbFn)
Callback<OriginalCbFnT> originalCbFn)
: AsynchronousContinuation<OriginalCbFnT>(originalCbFn),
caller(caller)
{}
@@ -123,11 +128,13 @@ public:
template<typename... Args>
void callOriginalCb(Args&&... args)
{
if (AsynchronousContinuation<OriginalCbFnT>::originalCbFn)
if (AsynchronousContinuation<OriginalCbFnT>::originalCallback
.callbackFn)
{
caller->getIoService().post(
std::bind(
AsynchronousContinuation<OriginalCbFnT>::originalCbFn,
AsynchronousContinuation<OriginalCbFnT>::originalCallback
.callbackFn,
std::forward<Args>(args)...));
}
}
@@ -0,0 +1,25 @@
#ifndef ASYNCHRONOUS_CONTINUATION_CHAIN_LINK_H
#define ASYNCHRONOUS_CONTINUATION_CHAIN_LINK_H
#include <memory>
namespace smo {
/**
* @brief Base class for all asynchronous continuation chain links
*
* This non-template base class provides type erasure for the continuation
* chain, allowing RTTI and dynamic casting when walking the chain.
*
* The chain walking logic can use dynamic_cast to determine the most
* derived type and perform appropriate operations.
*/
class AsynchronousContinuationChainLink
{
public:
virtual ~AsynchronousContinuationChainLink() = default;
};
} // namespace smo
#endif // ASYNCHRONOUS_CONTINUATION_CHAIN_LINK_H
+6 -13
View File
@@ -7,7 +7,7 @@
namespace smo {
// Forward declaration
class AsyncContinuation;
class AsynchronousContinuationChainLink;
/**
* @brief Callback class that wraps a function and its caller continuation
@@ -15,23 +15,16 @@ class AsyncContinuation;
* This class provides a way to pass both a callback function and the
* caller's continuation in a single object, enabling deadlock detection
* by walking the chain of continuations.
*
* Usage: Callback<CbFnT>{context, std::bind(...)}
*/
template<typename CbFnT>
class Callback
{
public:
/**
* @brief Constructor
* @param caller The caller's continuation
* @param cb The callback function to invoke
*/
Callback(std::shared_ptr<AsyncContinuation> caller, std::function<CbFnT> cb)
: callerContinuation(std::move(caller)), callback(std::move(cb))
{}
public:
std::shared_ptr<AsyncContinuation> callerContinuation;
std::function<CbFnT> callback;
// Aggregate initialization allows: Callback<CbFnT>{context, std::bind(...)}
std::shared_ptr<AsynchronousContinuationChainLink> callerContinuation;
CbFnT callbackFn;
};
} // namespace smo
+2 -1
View File
@@ -11,6 +11,7 @@
#include <lockSet.h>
#include <asynchronousContinuation.h>
#include <lockerAndInvokerBase.h>
#include <callback.h>
namespace smo {
@@ -21,7 +22,7 @@ class SerializedAsynchronousContinuation
public:
SerializedAsynchronousContinuation(
const std::shared_ptr<ComponentThread> &caller,
OriginalCbFnT originalCbFn,
Callback<OriginalCbFnT> originalCbFn,
std::vector<std::reference_wrapper<SpinLock>> requiredLocks = {})
: PostedAsynchronousContinuation<OriginalCbFnT>(caller, originalCbFn),
requiredLocks(*this, std::move(requiredLocks))
+3 -2
View File
@@ -8,6 +8,7 @@
#include <preprocessor.h>
#include <componentThread.h>
#include <user/deviceAttachmentSpec.h>
#include <callback.h>
namespace smo {
namespace sense_api {
@@ -44,10 +45,10 @@ typedef int (sal_mlo_finalizeIndFn)(void);
typedef void (sal_mlo_attachDeviceReqFn)(
const std::shared_ptr<device::DeviceAttachmentSpec>& desc,
const std::shared_ptr<ComponentThread>& componentThread,
sal_mlo_attachDeviceReqCbFn cb);
Callback<sal_mlo_attachDeviceReqCbFn> cb);
typedef void (sal_mlo_detachDeviceReqFn)(
const std::shared_ptr<device::DeviceAttachmentSpec>& desc,
sal_mlo_detachDeviceReqCbFn cb);
Callback<sal_mlo_detachDeviceReqCbFn> cb);
/**
* @brief Hooks provided by Salmanoff to senseApi libraries.