Skip to content

Commit

Permalink
Heap-ify ReadClient
Browse files Browse the repository at this point in the history
This 2/N PRs to heap-ify key IM pool-based objects.

This commit heap-ifies the ReadClient object. Specifically, it achieves
this indirectly by doing away with the pool-allocated scheme entirely
and letting applications control the instantiation and lifetime of the
ReadClient object.

Tests:
- REPL Reads
- Unit-tests
  • Loading branch information
mrjerryjohns committed Dec 17, 2021
1 parent a9b9fca commit 3de3b6d
Show file tree
Hide file tree
Showing 25 changed files with 802 additions and 2,430 deletions.
2 changes: 0 additions & 2 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,6 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") {
deps += [
":certification",
"${chip_root}/examples/shell/standalone:chip-shell",
"${chip_root}/src/app/tests/integration:chip-im-initiator",
"${chip_root}/src/app/tests/integration:chip-im-responder",
"${chip_root}/src/messaging/tests/echo:chip-echo-requester",
"${chip_root}/src/messaging/tests/echo:chip-echo-responder",
"${chip_root}/src/qrcodetool",
Expand Down
2 changes: 0 additions & 2 deletions src/app/DeviceProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ class DLL_EXPORT DeviceProxy

virtual bool GetAddress(Inet::IPAddress & addr, uint16_t & port) const { return false; }

virtual CHIP_ERROR ShutdownSubscriptions() { return CHIP_ERROR_NOT_IMPLEMENTED; }

virtual CHIP_ERROR SendWriteAttributeRequest(app::WriteClientHandle aHandle, Callback::Cancelable * onSuccessCallback,
Callback::Cancelable * onFailureCallback);

Expand Down
197 changes: 94 additions & 103 deletions src/app/InteractionModelEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,8 @@ void InteractionModelEngine::Shutdown()
mpExchangeMgr->CloseAllContextsForDelegate(obj);
return Loop::Continue;
});
mTimedHandlers.ReleaseAll();

for (auto & readClient : mReadClients)
{
if (!readClient.IsFree())
{
readClient.Shutdown();
}
}
mTimedHandlers.ReleaseAll();

for (auto & readHandler : mReadHandlers)
{
Expand All @@ -102,6 +95,15 @@ void InteractionModelEngine::Shutdown()
}
}

//
// We hold weak references to ReadClient objects. The application ultimately
// actually owns them, so it's on them to eventually shut them down and free them
// up.
//
// We just null out our tracker.
//
mpActiveReadClientList = nullptr;

for (auto & writeClient : mWriteClients)
{
if (!writeClient.IsFree())
Expand All @@ -127,43 +129,6 @@ void InteractionModelEngine::Shutdown()
mpExchangeMgr->UnregisterUnsolicitedMessageHandlerForProtocol(Protocols::InteractionModel::Id);
}

CHIP_ERROR InteractionModelEngine::NewReadClient(ReadClient ** const apReadClient, ReadClient::InteractionType aInteractionType,
ReadClient::Callback * aCallback)
{
*apReadClient = nullptr;
for (auto & readClient : mReadClients)
{
if (readClient.IsFree())
{
CHIP_ERROR err;

*apReadClient = &readClient;
err = readClient.Init(mpExchangeMgr, aCallback, aInteractionType);
if (CHIP_NO_ERROR != err)
{
*apReadClient = nullptr;
}
return err;
}
}
return CHIP_ERROR_NO_MEMORY;
}

uint32_t InteractionModelEngine::GetNumActiveReadClients() const
{
uint32_t numActive = 0;

for (auto & readClient : mReadClients)
{
if (!readClient.IsFree())
{
numActive++;
}
}

return numActive;
}

uint32_t InteractionModelEngine::GetNumActiveReadHandlers() const
{
uint32_t numActive = 0;
Expand Down Expand Up @@ -209,39 +174,6 @@ uint32_t InteractionModelEngine::GetNumActiveWriteHandlers() const
return numActive;
}

CHIP_ERROR InteractionModelEngine::ShutdownSubscription(uint64_t aSubscriptionId)
{
CHIP_ERROR err = CHIP_ERROR_KEY_NOT_FOUND;

for (auto & readClient : mReadClients)
{
if (!readClient.IsFree() && readClient.IsSubscriptionType() && readClient.IsMatchingClient(aSubscriptionId))
{
readClient.Shutdown();
err = CHIP_NO_ERROR;
}
}

return err;
}

CHIP_ERROR InteractionModelEngine::ShutdownSubscriptions(FabricIndex aFabricIndex, NodeId aPeerNodeId)
{
CHIP_ERROR err = CHIP_ERROR_KEY_NOT_FOUND;

for (ReadClient & readClient : mReadClients)
{
if (!readClient.IsFree() && readClient.IsSubscriptionType() && readClient.GetFabricIndex() == aFabricIndex &&
readClient.GetPeerNodeId() == aPeerNodeId)
{
readClient.Shutdown();
err = CHIP_NO_ERROR;
}
}

return err;
}

CHIP_ERROR InteractionModelEngine::NewWriteClient(WriteClientHandle & apWriteClient, WriteClient::Callback * apCallback,
const Optional<uint16_t> & aTimedWriteTimeoutMs)
{
Expand Down Expand Up @@ -392,18 +324,21 @@ CHIP_ERROR InteractionModelEngine::OnUnsolicitedReportData(Messaging::ExchangeCo
uint64_t subscriptionId = 0;
ReturnLogErrorOnFailure(report.GetSubscriptionId(&subscriptionId));

for (auto & readClient : mReadClients)
for (auto * readClient = mpActiveReadClientList; readClient != nullptr; readClient = readClient->GetNextClient())
{
if (!readClient.IsSubscriptionIdle())
if (!readClient->IsSubscriptionIdle())
{
continue;
}
if (!readClient.IsMatchingClient(subscriptionId))

if (!readClient->IsMatchingClient(subscriptionId))
{
continue;
}
return readClient.OnUnsolicitedReportData(apExchangeContext, std::move(aPayload));

return readClient->OnUnsolicitedReportData(apExchangeContext, std::move(aPayload));
}

return CHIP_NO_ERROR;
}

Expand Down Expand Up @@ -462,40 +397,96 @@ void InteractionModelEngine::OnResponseTimeout(Messaging::ExchangeContext * ec)
ChipLogValueExchange(ec));
}

CHIP_ERROR InteractionModelEngine::SendReadRequest(ReadPrepareParams & aReadPrepareParams, ReadClient::Callback * aCallback)
uint16_t InteractionModelEngine::GetWriteClientArrayIndex(const WriteClient * const apWriteClient) const
{
ReadClient * client = nullptr;
CHIP_ERROR err = CHIP_NO_ERROR;
ReturnErrorOnFailure(NewReadClient(&client, ReadClient::InteractionType::Read, aCallback));
err = client->SendRequest(aReadPrepareParams);
if (err != CHIP_NO_ERROR)
{
client->Shutdown();
}
return err;
return static_cast<uint16_t>(apWriteClient - mWriteClients);
}

CHIP_ERROR InteractionModelEngine::SendSubscribeRequest(ReadPrepareParams & aReadPrepareParams, ReadClient::Callback * aCallback)
uint16_t InteractionModelEngine::GetReadHandlerArrayIndex(const ReadHandler * const apReadHandler) const
{
ReadClient * client = nullptr;
ReturnErrorOnFailure(NewReadClient(&client, ReadClient::InteractionType::Subscribe, aCallback));
ReturnErrorOnFailure(client->SendRequest(aReadPrepareParams));
return CHIP_NO_ERROR;
return static_cast<uint16_t>(apReadHandler - mReadHandlers);
}

uint16_t InteractionModelEngine::GetReadClientArrayIndex(const ReadClient * const apReadClient) const
void InteractionModelEngine::AddReadClient(ReadClient * apReadClient)
{
return static_cast<uint16_t>(apReadClient - mReadClients);
ReadClient * pPrevListItem = nullptr;
ReadClient * pCurListItem = mpActiveReadClientList;

while (pCurListItem)
{
pPrevListItem = pCurListItem;
pCurListItem = pCurListItem->GetNextClient();
}

if (pPrevListItem)
{
pPrevListItem->SetNextClient(apReadClient);
}
else
{
mpActiveReadClientList = apReadClient;
}

apReadClient->SetNextClient(nullptr);
}

uint16_t InteractionModelEngine::GetWriteClientArrayIndex(const WriteClient * const apWriteClient) const
void InteractionModelEngine::RemoveReadClient(ReadClient * apReadClient)
{
return static_cast<uint16_t>(apWriteClient - mWriteClients);
ReadClient * pPrevListItem = nullptr;
ReadClient * pCurListItem = mpActiveReadClientList;

while (pCurListItem != apReadClient)
{
pPrevListItem = pCurListItem;
pCurListItem = pCurListItem->GetNextClient();
}

//
// Item must exist in this tracker list. If not, there's a bug somewhere.
//
VerifyOrDie(pCurListItem != nullptr);

if (pPrevListItem)
{
pPrevListItem->SetNextClient(apReadClient->GetNextClient());
}
else
{
mpActiveReadClientList = apReadClient->GetNextClient();
}

apReadClient->SetNextClient(nullptr);
}

uint16_t InteractionModelEngine::GetReadHandlerArrayIndex(const ReadHandler * const apReadHandler) const
size_t InteractionModelEngine::GetNumActiveReadClients()
{
return static_cast<uint16_t>(apReadHandler - mReadHandlers);
ReadClient * pListItem = mpActiveReadClientList;
size_t count = 0;

while (pListItem)
{
pListItem = pListItem->GetNextClient();
count++;
}

return count;
}

bool InteractionModelEngine::InActiveReadClientList(ReadClient * apReadClient)
{
ReadClient * pListItem = mpActiveReadClientList;

while (pListItem)
{
if (pListItem == apReadClient)
{
return true;
}

pListItem = pListItem->GetNextClient();
}

return false;
}

void InteractionModelEngine::ReleaseClusterInfoList(ClusterInfo *& aClusterInfo)
Expand Down
Loading

0 comments on commit 3de3b6d

Please sign in to comment.