diff --git a/src/app/clusters/bindings/BindingManager.cpp b/src/app/clusters/bindings/BindingManager.cpp index d00244dcd4a658..2f8cb1853226a8 100644 --- a/src/app/clusters/bindings/BindingManager.cpp +++ b/src/app/clusters/bindings/BindingManager.cpp @@ -162,15 +162,9 @@ void BindingManager::HandleDeviceConnected(OperationalDeviceProxy * device) fabricToRemove = entry.fabricIndex; nodeToRemove = entry.nodeId; - BindingManagerContext * context = static_cast(pendingNotification.mContext); - mBoundDeviceChangedHandler(entry, device, context->GetContext()); + mBoundDeviceChangedHandler(entry, device, pendingNotification.mContext->GetContext()); - context->DecrementConsumersNumber(); - if (context->GetConsumersNumber() == 0) - { - mBoundDeviceContextReleaseHandler(context->GetContext()); - Platform::Delete(context); - } + pendingNotification.mContext->DecrementConsumersNumber(); } } mPendingNotificationMap.RemoveAllEntriesForNode(fabricToRemove, nodeToRemove); @@ -199,10 +193,10 @@ CHIP_ERROR BindingManager::NotifyBoundClusterChanged(EndpointId endpoint, Cluste { VerifyOrReturnError(mInitParams.mFabricTable != nullptr, CHIP_ERROR_INCORRECT_STATE); VerifyOrReturnError(mBoundDeviceChangedHandler, CHIP_NO_ERROR); - VerifyOrReturnError(mBoundDeviceContextReleaseHandler, CHIP_NO_ERROR); - CHIP_ERROR error = CHIP_NO_ERROR; - BindingManagerContext * bindingContext = Platform::New(static_cast(context)); + CHIP_ERROR error = CHIP_NO_ERROR; + auto * bindingContext = mPendingNotificationMap.NewPendingNotificationContext(context); + VerifyOrReturnError(bindingContext != nullptr, CHIP_ERROR_NO_MEMORY); bindingContext->IncrementConsumersNumber(); @@ -223,8 +217,7 @@ CHIP_ERROR BindingManager::NotifyBoundClusterChanged(EndpointId endpoint, Cluste } else { - mPendingNotificationMap.AddPendingNotification(iter.GetIndex(), static_cast(bindingContext)); - bindingContext->IncrementConsumersNumber(); + mPendingNotificationMap.AddPendingNotification(iter.GetIndex(), bindingContext); error = EstablishConnection(iter->fabricIndex, iter->nodeId); SuccessOrExit(error == CHIP_NO_ERROR); } @@ -239,13 +232,6 @@ CHIP_ERROR BindingManager::NotifyBoundClusterChanged(EndpointId endpoint, Cluste exit: bindingContext->DecrementConsumersNumber(); - // Call release bindingContext handler only if any pending notification is not going to use it. - if (bindingContext->GetConsumersNumber() == 0) - { - mBoundDeviceContextReleaseHandler(bindingContext->GetContext()); - Platform::Delete(bindingContext); - } - return error; } diff --git a/src/app/clusters/bindings/BindingManager.h b/src/app/clusters/bindings/BindingManager.h index fa3c2c4b1a6e4a..28fc11959e62ec 100644 --- a/src/app/clusters/bindings/BindingManager.h +++ b/src/app/clusters/bindings/BindingManager.h @@ -26,26 +26,6 @@ namespace chip { -class BindingManagerContext -{ -public: - BindingManagerContext(void * context) : mContext(context) {} - void * GetContext() { return mContext; }; - uint8_t GetConsumersNumber() { return mConsumersNumber; } - void IncrementConsumersNumber() { mConsumersNumber++; } - void DecrementConsumersNumber() - { - if (mConsumersNumber > 0) - { - mConsumersNumber--; - } - } - -private: - void * mContext; - uint8_t mConsumersNumber = 0; -}; - /** * Application callback function when a cluster associated with a binding changes. * @@ -64,7 +44,7 @@ using BoundDeviceChangedHandler = void (*)(const EmberBindingTableEntry & bindin * Application callback function when a context used in NotifyBoundClusterChanged will not be needed and should be * released. */ -using BoundDeviceContextReleaseHandler = void (*)(void * context); +using BoundDeviceContextReleaseHandler = PendingNotificationContextReleaseHandler; struct BindingManagerInitParams { @@ -103,7 +83,7 @@ class BindingManager */ void RegisterBoundDeviceContextReleaseHandler(BoundDeviceContextReleaseHandler handler) { - mBoundDeviceContextReleaseHandler = handler; + mPendingNotificationMap.RegisterPendingNotificationContextReleaseHandler(handler); } CHIP_ERROR Init(const BindingManagerInitParams & params); @@ -153,7 +133,6 @@ class BindingManager PendingNotificationMap mPendingNotificationMap; BoundDeviceChangedHandler mBoundDeviceChangedHandler; - BoundDeviceContextReleaseHandler mBoundDeviceContextReleaseHandler; BindingManagerInitParams mInitParams; Callback::Callback mOnConnectedCallback; diff --git a/src/app/clusters/bindings/PendingNotificationMap.cpp b/src/app/clusters/bindings/PendingNotificationMap.cpp index 7c992677587532..6676a82b779d4d 100644 --- a/src/app/clusters/bindings/PendingNotificationMap.cpp +++ b/src/app/clusters/bindings/PendingNotificationMap.cpp @@ -79,11 +79,15 @@ CHIP_ERROR PendingNotificationMap::FindLRUConnectPeer(FabricIndex * fabric, Node return CHIP_ERROR_NOT_FOUND; } -void PendingNotificationMap::AddPendingNotification(uint8_t bindingEntryId, void * context) +void PendingNotificationMap::AddPendingNotification(uint8_t bindingEntryId, PendingNotificationContext * context) { RemoveEntry(bindingEntryId); mPendingBindingEntries[mNumEntries] = bindingEntryId; mPendingContexts[mNumEntries] = context; + if (context) + { + context->IncrementConsumersNumber(); + } mNumEntries++; } @@ -98,6 +102,10 @@ void PendingNotificationMap::RemoveEntry(uint8_t bindingEntryId) mPendingContexts[newEntryCount] = mPendingContexts[i]; newEntryCount++; } + else if (mPendingContexts[i] != nullptr) + { + mPendingContexts[i]->DecrementConsumersNumber(); + } } mNumEntries = newEntryCount; } @@ -114,6 +122,10 @@ void PendingNotificationMap::RemoveAllEntriesForNode(FabricIndex fabric, NodeId mPendingContexts[newEntryCount] = mPendingContexts[i]; newEntryCount++; } + else if (mPendingContexts[i] != nullptr) + { + mPendingContexts[i]->DecrementConsumersNumber(); + } } mNumEntries = newEntryCount; } @@ -130,6 +142,10 @@ void PendingNotificationMap::RemoveAllEntriesForFabric(FabricIndex fabric) mPendingContexts[newEntryCount] = mPendingContexts[i]; newEntryCount++; } + else if (mPendingContexts[i] != nullptr) + { + mPendingContexts[i]->DecrementConsumersNumber(); + } } mNumEntries = newEntryCount; } diff --git a/src/app/clusters/bindings/PendingNotificationMap.h b/src/app/clusters/bindings/PendingNotificationMap.h index 2b66fa7efa97fc..fad96ea78cbb74 100644 --- a/src/app/clusters/bindings/PendingNotificationMap.h +++ b/src/app/clusters/bindings/PendingNotificationMap.h @@ -21,11 +21,49 @@ namespace chip { +/** + * Application callback function when a context used in PendingNotificationEntry will not be needed and should be + * released. + */ +using PendingNotificationContextReleaseHandler = void (*)(void * context); + +class PendingNotificationContext +{ +public: + PendingNotificationContext(void * context, PendingNotificationContextReleaseHandler contextReleaseHandler) : + mContext(context), mPendingNotificationContextReleaseHandler(contextReleaseHandler) + {} + void * GetContext() { return mContext; }; + uint8_t GetConsumersNumber() { return mConsumersNumber; } + void IncrementConsumersNumber() { mConsumersNumber++; } + void DecrementConsumersNumber() + { + if (mConsumersNumber > 0) + { + mConsumersNumber--; + } + else + { + // Release the context only if there is no pending notification pointing to it context. + if (mPendingNotificationContextReleaseHandler != nullptr) + { + mPendingNotificationContextReleaseHandler(mContext); + } + Platform::Delete(this); + } + } + +private: + void * mContext; + uint8_t mConsumersNumber = 0; + PendingNotificationContextReleaseHandler mPendingNotificationContextReleaseHandler; +}; + struct PendingNotificationEntry { public: uint8_t mBindingEntryId; - void * mContext; + PendingNotificationContext * mContext; }; // The pool for all the pending comands. @@ -67,7 +105,7 @@ class PendingNotificationMap CHIP_ERROR FindLRUConnectPeer(FabricIndex * fabric, NodeId * node); - void AddPendingNotification(uint8_t bindingEntryId, void * context); + void AddPendingNotification(uint8_t bindingEntryId, PendingNotificationContext * context); void RemoveEntry(uint8_t bindingEntryId); @@ -77,9 +115,20 @@ class PendingNotificationMap void RemoveAllEntriesForFabric(FabricIndex fabric); + void RegisterPendingNotificationContextReleaseHandler(PendingNotificationContextReleaseHandler handler) + { + mPendingNotificationContextReleaseHandler = handler; + } + + PendingNotificationContext * NewPendingNotificationContext(void * context) + { + return Platform::New(context, mPendingNotificationContextReleaseHandler); + }; + private: uint8_t mPendingBindingEntries[kMaxPendingNotifications]; - void * mPendingContexts[kMaxPendingNotifications]; + PendingNotificationContext * mPendingContexts[kMaxPendingNotifications]; + PendingNotificationContextReleaseHandler mPendingNotificationContextReleaseHandler; uint8_t mNumEntries = 0; };