Remove dependency of InteractionModelEngine in CommandHandler (#31830)
* Remove dependency of InteractionModelEngine in CommandHandler
* Address comments and fix tizen test
* Fix tizen example
* Fix segfault in CommandHandler::Handle::Get()
* Change CommandHandler::Callback function name
* Add virtual function in CommandHandler::Callback in
CommandResponseSender
* Add mpCallback null checks
* Add weak reference to CommandHandler
* Remove magic number from ImEngine
* self clean up
* Restyled by clang-format
* Use IntrusiveList for weak references of the Handles
* Update src/app/CommandHandler.cpp
Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>
* Update src/app/CommandHandler.cpp
Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>
* Update src/app/CommandHandler.h
Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>
* compile fix after renaming
---------
Co-authored-by: Restyled.io <commits@restyled.io>
Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>
diff --git a/src/app/CommandHandler.cpp b/src/app/CommandHandler.cpp
index 005067c..89ff52f 100644
--- a/src/app/CommandHandler.cpp
+++ b/src/app/CommandHandler.cpp
@@ -35,6 +35,7 @@
#include <lib/core/CHIPConfig.h>
#include <lib/core/TLVData.h>
#include <lib/core/TLVUtilities.h>
+#include <lib/support/IntrusiveList.h>
#include <lib/support/TypeTraits.h>
#include <platform/LockTracker.h>
#include <protocols/secure_channel/Constants.h>
@@ -58,6 +59,11 @@
}
}
+CommandHandler::~CommandHandler()
+{
+ InvalidateHandles();
+}
+
CHIP_ERROR CommandHandler::AllocateBuffer()
{
// We should only allocate a buffer if we will be sending out a response.
@@ -266,6 +272,7 @@
// reference is the stack shutting down, in which case Close() is not called. So the below check should always pass.
VerifyOrDieWithMsg(mPendingWork == 0, DataManagement, "CommandHandler::Close() called with %u unfinished async work items",
static_cast<unsigned int>(mPendingWork));
+ InvalidateHandles();
if (mpCallback)
{
@@ -273,16 +280,40 @@
}
}
-void CommandHandler::IncrementHoldOff()
+void CommandHandler::AddToHandleList(Handle * apHandle)
{
- mPendingWork++;
+ mpHandleList.PushBack(apHandle);
}
-void CommandHandler::DecrementHoldOff()
+void CommandHandler::RemoveFromHandleList(Handle * apHandle)
{
+ VerifyOrDie(mpHandleList.Contains(apHandle));
+ mpHandleList.Remove(apHandle);
+}
+
+void CommandHandler::InvalidateHandles()
+{
+ for (auto handle = mpHandleList.begin(); handle != mpHandleList.end(); ++handle)
+ {
+ handle->Invalidate();
+ }
+}
+
+void CommandHandler::IncrementHoldOff(Handle * apHandle)
+{
+ mPendingWork++;
+ AddToHandleList(apHandle);
+}
+
+void CommandHandler::DecrementHoldOff(Handle * apHandle)
+{
+
mPendingWork--;
ChipLogDetail(DataManagement, "Decreasing reference count for CommandHandler, remaining %u",
static_cast<unsigned int>(mPendingWork));
+
+ RemoveFromHandleList(apHandle);
+
if (mPendingWork != 0)
{
return;
@@ -771,35 +802,35 @@
return mpResponder->GetAccessingFabricIndex();
}
+void CommandHandler::Handle::Init(CommandHandler * handler)
+{
+ if (handler != nullptr)
+ {
+ handler->IncrementHoldOff(this);
+ mpHandler = handler;
+ }
+}
+
CommandHandler * CommandHandler::Handle::Get()
{
// Not safe to work with CommandHandler in parallel with other Matter work.
assertChipStackLockedByCurrentThread();
- return (mMagic == InteractionModelEngine::GetInstance()->GetMagicNumber()) ? mpHandler : nullptr;
+ return mpHandler;
}
void CommandHandler::Handle::Release()
{
if (mpHandler != nullptr)
{
- if (mMagic == InteractionModelEngine::GetInstance()->GetMagicNumber())
- {
- mpHandler->DecrementHoldOff();
- }
- mpHandler = nullptr;
- mMagic = 0;
+ mpHandler->DecrementHoldOff(this);
+ Invalidate();
}
}
-CommandHandler::Handle::Handle(CommandHandler * handle)
+CommandHandler::Handle::Handle(CommandHandler * handler)
{
- if (handle != nullptr)
- {
- handle->IncrementHoldOff();
- mpHandler = handle;
- mMagic = InteractionModelEngine::GetInstance()->GetMagicNumber();
- }
+ Init(handler);
}
CHIP_ERROR CommandHandler::FinalizeInvokeResponseMessageAndPrepareNext()
diff --git a/src/app/CommandHandler.h b/src/app/CommandHandler.h
index 2eed73d..cce1987 100644
--- a/src/app/CommandHandler.h
+++ b/src/app/CommandHandler.h
@@ -41,6 +41,7 @@
#include <lib/support/BitFlags.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/DLLUtil.h>
+#include <lib/support/IntrusiveList.h>
#include <lib/support/Scoped.h>
#include <lib/support/logging/CHIPLogging.h>
#include <messaging/ExchangeHolder.h>
@@ -110,29 +111,26 @@
* The Invoke Response will not be sent until all outstanding Handles have
* been destroyed or have had Release called.
*/
- class Handle
+ class Handle : public IntrusiveListNodeBase<>
{
public:
Handle() {}
Handle(const Handle & handle) = delete;
Handle(Handle && handle)
{
- mpHandler = handle.mpHandler;
- mMagic = handle.mMagic;
- handle.mpHandler = nullptr;
- handle.mMagic = 0;
+ Init(handle.mpHandler);
+ handle.Release();
}
Handle(decltype(nullptr)) {}
- Handle(CommandHandler * handle);
+ Handle(CommandHandler * handler);
~Handle() { Release(); }
Handle & operator=(Handle && handle)
{
Release();
- mpHandler = handle.mpHandler;
- mMagic = handle.mMagic;
- handle.mpHandler = nullptr;
- handle.mMagic = 0;
+ Init(handle.mpHandler);
+
+ handle.Release();
return *this;
}
@@ -143,16 +141,19 @@
}
/**
- * Get the CommandHandler object it holds. Get() may return a nullptr if the CommandHandler object is holds is no longer
+ * Get the CommandHandler object it holds. Get() may return a nullptr if the CommandHandler object it holds is no longer
* valid.
*/
CommandHandler * Get();
void Release();
+ void Invalidate() { mpHandler = nullptr; }
+
private:
+ void Init(CommandHandler * handler);
+
CommandHandler * mpHandler = nullptr;
- uint32_t mMagic = 0;
};
// Previously we kept adding arguments with default values individually as parameters. This is because there
@@ -192,6 +193,14 @@
CommandHandler(Callback * apCallback);
/*
+ * Destructor.
+ *
+ * The call will also invalidate all Handles created for this CommandHandler.
+ *
+ */
+ ~CommandHandler();
+
+ /*
* Constructor to override the number of supported paths per invoke and command responder.
*
* The callback and any pointers passed via TestOnlyOverrides must outlive this
@@ -525,13 +534,13 @@
* Users should use CommandHandler::Handle for management the lifespan of the CommandHandler.
* DefRef should be released in reasonable time, and Close() should only be called when the refcount reached 0.
*/
- void IncrementHoldOff();
+ void IncrementHoldOff(Handle * apHandle);
/**
* DecrementHoldOff is used by CommandHandler::Handle for decreasing the refcount of the CommandHandler.
* When refcount reached 0, CommandHandler will send the response to the peer and shutdown.
*/
- void DecrementHoldOff();
+ void DecrementHoldOff(Handle * apHandle);
/*
* Allocates a packet buffer used for encoding an invoke response payload.
@@ -672,12 +681,20 @@
size_t MaxPathsPerInvoke() const { return mMaxPathsPerInvoke; }
+ void AddToHandleList(Handle * handle);
+
+ void RemoveFromHandleList(Handle * handle);
+
+ void InvalidateHandles();
+
bool TestOnlyIsInIdleState() const { return mState == State::Idle; }
Callback * mpCallback = nullptr;
InvokeResponseMessage::Builder mInvokeResponseBuilder;
TLV::TLVType mDataElementContainerType = TLV::kTLVType_NotSpecified;
size_t mPendingWork = 0;
+ /* List to store all currently-outstanding Handles for this Command Handler.*/
+ IntrusiveList<Handle> mpHandleList;
chip::System::PacketBufferTLVWriter mCommandMessageWriter;
TLV::TLVWriter mBackupWriter;
diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp
index 64c06f9..9752876 100644
--- a/src/app/InteractionModelEngine.cpp
+++ b/src/app/InteractionModelEngine.cpp
@@ -85,7 +85,6 @@
ReturnErrorOnFailure(mpExchangeMgr->RegisterUnsolicitedMessageHandlerForProtocol(Protocols::InteractionModel::Id, this));
mReportingEngine.Init();
- mMagic++;
StatusIB::RegisterErrorFormatter();
@@ -111,9 +110,6 @@
mCommandHandlerList = nullptr;
- // Increase magic number to invalidate all Handle-s.
- mMagic++;
-
mCommandResponderObjs.ReleaseAll();
mTimedHandlers.ForEachActiveObject([this](TimedHandler * obj) -> Loop {
diff --git a/src/app/InteractionModelEngine.h b/src/app/InteractionModelEngine.h
index baf02c6..87c497c 100644
--- a/src/app/InteractionModelEngine.h
+++ b/src/app/InteractionModelEngine.h
@@ -192,11 +192,6 @@
*/
WriteHandler * ActiveWriteHandlerAt(unsigned int aIndex);
- /**
- * The Magic number of this InteractionModelEngine, the magic number is set during Init()
- */
- uint32_t GetMagicNumber() const { return mMagic; }
-
reporting::Engine & GetReportingEngine() { return mReportingEngine; }
reporting::ReportScheduler * GetReportScheduler() { return mReportScheduler; }
@@ -706,10 +701,6 @@
CASESessionManager * mpCASESessionMgr = nullptr;
SubscriptionResumptionStorage * mpSubscriptionResumptionStorage = nullptr;
-
- // A magic number for tracking values between stack Shutdown()-s and Init()-s.
- // An ObjectHandle is valid iff. its magic equals to this one.
- uint32_t mMagic = 0;
};
} // namespace app