Skip to content

Commit

Permalink
Faster chip-tool builds. (#11699)
Browse files Browse the repository at this point in the history
Uses simpler templates for command sending to improve build times.
  • Loading branch information
bzbarsky-apple authored Nov 11, 2021
1 parent 4ae5f21 commit 14eaa07
Show file tree
Hide file tree
Showing 25 changed files with 1,034 additions and 2,903 deletions.
1 change: 1 addition & 0 deletions examples/chip-tool/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ executable("chip-tool") {
"commands/common/CHIPCommand.cpp",
"commands/common/CHIPCommand.h",
"commands/common/Command.cpp",
"commands/common/CommandInvoker.h",
"commands/common/Commands.cpp",
"commands/discover/DiscoverCommand.cpp",
"commands/discover/DiscoverCommissionablesCommand.cpp",
Expand Down
166 changes: 166 additions & 0 deletions examples/chip-tool/commands/common/CommandInvoker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/*
* Copyright (c) 2021 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#pragma once

#include <app-common/zap-generated/cluster-objects.h>
#include <app/CommandSender.h>
#include <app/DeviceProxy.h>
#include <app/InteractionModelEngine.h>
#include <app/util/error-mapping.h>

namespace chip {
namespace Controller {
namespace detail {
template <typename ResponseType>
class ResponseReceiver : public app::CommandSender::Callback
{
public:
using SuccessCallback = void (*)(void * context, const ResponseType & data);
using FailureCallback = void (*)(void * context, EmberAfStatus status);

virtual ~ResponseReceiver() {}

protected:
ResponseReceiver(void * aContext, SuccessCallback aOnSuccess, FailureCallback aOnError) :
mContext(aContext), mOnSuccess(aOnSuccess), mOnError(aOnError)
{}

inline void OnResponse(app::CommandSender * aCommandSender, const app::ConcreteCommandPath & aPath,
const app::StatusIB & aStatus, TLV::TLVReader * aData) override;

void OnError(const app::CommandSender * aCommandSender, const app::StatusIB & aStatus, CHIP_ERROR aError) override
{
mOnError(mContext, app::ToEmberAfStatus(aStatus.mStatus));
}

void OnDone(app::CommandSender * aCommandSender) override
{
Platform::Delete(aCommandSender);
Platform::Delete(this);
}

private:
void * mContext;
SuccessCallback mOnSuccess;
FailureCallback mOnError;
};

template <typename RequestType>
class CommandInvoker final : public ResponseReceiver<typename RequestType::ResponseType>
{
using Super = ResponseReceiver<typename RequestType::ResponseType>;

public:
CommandInvoker(void * aContext, typename Super::SuccessCallback aOnSuccess, typename Super::FailureCallback aOnError) :
Super(aContext, aOnSuccess, aOnError)
{}

/**
* Use of CommandInvoker looks as follows:
*
* auto invoker = CommandInvoker<type>::Alloc(args);
* VerifyOrReturnError(invoker != nullptr, CHIP_ERROR_NO_MEMORY);
* ReturnErrorOnFailure(invoker->InvokeCommand(args));
* invoker.release(); // The invoker will deallocate itself now.
*/
static auto Alloc(void * aContext, typename Super::SuccessCallback aOnSuccess, typename Super::FailureCallback aOnError)
{
return Platform::MakeUnique<CommandInvoker>(aContext, aOnSuccess, aOnError);
}

CHIP_ERROR InvokeCommand(DeviceProxy * aDevice, EndpointId aEndpoint, const RequestType & aRequestData)
{
app::CommandPathParams commandPath = { aEndpoint, 0, RequestType::GetClusterId(), RequestType::GetCommandId(),
(app::CommandPathFlags::kEndpointIdValid) };
auto commandSender = Platform::MakeUnique<app::CommandSender>(this, aDevice->GetExchangeManager());
VerifyOrReturnError(commandSender != nullptr, CHIP_ERROR_NO_MEMORY);

ReturnErrorOnFailure(commandSender->AddRequestData(commandPath, aRequestData));
ReturnErrorOnFailure(commandSender->SendCommandRequest(aDevice->GetSecureSession().Value()));
commandSender.release();
return CHIP_NO_ERROR;
}
};

template <typename ResponseType>
void ResponseReceiver<ResponseType>::OnResponse(app::CommandSender * aCommandSender, const app::ConcreteCommandPath & aPath,
const app::StatusIB & aStatus, TLV::TLVReader * aData)
{
ResponseType response;
CHIP_ERROR err = CHIP_NO_ERROR;

//
// We're expecting response data in this variant of OnResponse. Consequently, aReader should always be
// non-null. If it is, it means we received a success status code instead, which is not what was expected.
//
VerifyOrExit(aData != nullptr, err = CHIP_ERROR_SCHEMA_MISMATCH);

//
// Validate that the data response we received matches what we expect in terms of its cluster and command IDs.
//
VerifyOrExit(aPath.mClusterId == ResponseType::GetClusterId() && aPath.mCommandId == ResponseType::GetCommandId(),
err = CHIP_ERROR_SCHEMA_MISMATCH);

err = app::DataModel::Decode(*aData, response);
SuccessOrExit(err);

mOnSuccess(mContext, response);

exit:
if (err != CHIP_NO_ERROR)
{
mOnError(mContext, app::ToEmberAfStatus(Protocols::InteractionModel::Status::Failure));
}
}

template <>
inline void ResponseReceiver<app::DataModel::NullObjectType>::OnResponse(app::CommandSender * aCommandSender,
const app::ConcreteCommandPath & aPath,
const app::StatusIB & aStatus, TLV::TLVReader * aData)
{
//
// If we got a valid reader, it means we received response data that we were not expecting to receive.
//
if (aData != nullptr)
{
mOnError(mContext, app::ToEmberAfStatus(Protocols::InteractionModel::Status::Failure));
return;
}

app::DataModel::NullObjectType nullResp;
mOnSuccess(mContext, nullResp);
}

} // namespace detail

template <typename RequestType>
CHIP_ERROR InvokeCommand(DeviceProxy * aDevice, void * aContext,
typename detail::CommandInvoker<RequestType>::SuccessCallback aSuccessCallback,
typename detail::CommandInvoker<RequestType>::FailureCallback aFailureCallback, EndpointId aEndpoint,
const RequestType & aRequestData)
{
auto invoker = detail::CommandInvoker<RequestType>::Alloc(aContext, aSuccessCallback, aFailureCallback);
VerifyOrReturnError(invoker != nullptr, CHIP_ERROR_NO_MEMORY);
ReturnErrorOnFailure(invoker->InvokeCommand(aDevice, aEndpoint, aRequestData));
invoker.release();
return CHIP_NO_ERROR;
}

} // namespace Controller
} // namespace chip
5 changes: 2 additions & 3 deletions examples/chip-tool/templates/commands.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <app/data-model/DecodableList.h>
#include <app/data-model/Nullable.h>
#include <commands/clusters/ModelCommand.h>
#include <commands/common/CommandInvoker.h>
#include <lib/core/CHIPSafeCasts.h>
#include <lib/support/BytesToHex.h>
#include <lib/support/Span.h>
Expand Down Expand Up @@ -411,9 +412,7 @@ public:
{{/if}}
{{/chip_cluster_command_non_expanded_arguments}}

chip::Controller::{{asUpperCamelCase parent.name}}Cluster cluster;
cluster.Associate(device, endpointId);
return cluster.InvokeCommand(mRequest, this, {{#if hasSpecificResponse}}On{{asUpperCamelCase parent.name}}{{asUpperCamelCase response.name}}Success{{else}}OnDefaultSuccess{{/if}}, OnDefaultFailure);
return chip::Controller::InvokeCommand(device, this, {{#if hasSpecificResponse}}On{{asUpperCamelCase parent.name}}{{asUpperCamelCase response.name}}Success{{else}}OnDefaultSuccess{{/if}}, OnDefaultFailure, endpointId, mRequest);
}

private:
Expand Down
10 changes: 6 additions & 4 deletions examples/chip-tool/templates/partials/test_cluster.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,6 @@ class {{filename}}: public TestCommand

CHIP_ERROR {{>testCommand}}()
{
chip::Controller::{{asUpperCamelCase cluster}}ClusterTest cluster;
cluster.Associate(mDevice, {{endpoint}});

{{#if isCommand}}
using RequestType = chip::app::Clusters::{{asUpperCamelCase cluster}}::Commands::{{asUpperCamelCase command}}::Type;

Expand All @@ -155,8 +152,13 @@ class {{filename}}: public TestCommand
auto failure = [](void * context, EmberAfStatus status) {
(static_cast<{{filename}} *>(context))->OnFailureResponse_{{index}}(status);
};
{{#if async}}ReturnErrorOnFailure({{else}}return {{/if}}cluster.InvokeCommand(request, this, success, failure){{#if async}}){{/if}};

ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevice, this, success, failure, {{endpoint}}, request));
{{#unless async}}return CHIP_NO_ERROR;{{/unless}}
{{else}}
chip::Controller::{{asUpperCamelCase cluster}}ClusterTest cluster;
cluster.Associate(mDevice, {{endpoint}});

{{#chip_tests_item_parameters}}
{{zapTypeToEncodableClusterObjectType type ns=parent.cluster}} {{asLowerCamelCase name}}Argument;
{{>commandValue ns=parent.cluster container=(concat (asLowerCamelCase name) "Argument") definedValue=definedValue}}
Expand Down
1 change: 1 addition & 0 deletions examples/chip-tool/templates/tests-commands.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#pragma once

#include <commands/tests/TestCommand.h>
#include <commands/common/CommandInvoker.h>

{{>test_cluster tests=(getTests)}}

Expand Down
1 change: 0 additions & 1 deletion src/app/chip_data_model.gni
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ template("chip_data_model") {
sources += [
"${invoker.zap_pregenerated_dir}/CHIPClusters.cpp",
"${invoker.zap_pregenerated_dir}/CHIPClusters.h",
"${invoker.zap_pregenerated_dir}/CHIPClustersInvoke.cpp",
"${invoker.zap_pregenerated_dir}/attribute-size.cpp",
"${invoker.zap_pregenerated_dir}/callback-stub.cpp",
]
Expand Down
5 changes: 0 additions & 5 deletions src/app/zap-templates/app-templates.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,6 @@
"path": "templates/app/CHIPClusters-src.zapt",
"name": "C++ ZCL API",
"output": "CHIPClusters.cpp"
},
{
"path": "templates/app/CHIPClustersInvoke-src.zapt",
"name": "C++ ZCL Invoke API",
"output": "CHIPClustersInvoke.cpp"
}
]
}
17 changes: 16 additions & 1 deletion src/controller/CHIPCluster.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,22 @@ class DLL_EXPORT ClusterBase
template <typename RequestDataT>
CHIP_ERROR InvokeCommand(const RequestDataT & requestData, void * context,
CommandResponseSuccessCallback<typename RequestDataT::ResponseType> successCb,
CommandResponseFailureCallback failureCb);
CommandResponseFailureCallback failureCb)
{
VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE);

auto onSuccessCb = [context, successCb](const app::ConcreteCommandPath & commandPath, const app::StatusIB & aStatus,
const typename RequestDataT::ResponseType & responseData) {
successCb(context, responseData);
};

auto onFailureCb = [context, failureCb](const app::StatusIB & aStatus, CHIP_ERROR aError) {
failureCb(context, app::ToEmberAfStatus(aStatus.mStatus));
};

return InvokeCommandRequest(mDevice->GetExchangeManager(), mDevice->GetSecureSession().Value(), mEndpoint, requestData,
onSuccessCb, onFailureCb);
};

/**
* Functions for writing attributes. We have lots of different
Expand Down
4 changes: 0 additions & 4 deletions src/darwin/Framework/CHIP.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
1ED276E026C57CF000547A89 /* CHIPCallbackBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1ED276DF26C57CF000547A89 /* CHIPCallbackBridge.mm */; };
1ED276E226C5812A00547A89 /* CHIPCluster.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1ED276E126C5812A00547A89 /* CHIPCluster.mm */; };
1ED276E426C5832500547A89 /* CHIPCluster.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ED276E326C5832500547A89 /* CHIPCluster.h */; settings = {ATTRIBUTES = (Public, ); }; };
1EF900A0273AC39C006A4018 /* CHIPClustersInvoke.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1EF9009E273AC39C006A4018 /* CHIPClustersInvoke.cpp */; };
2C1B027A2641DB4E00780EF1 /* CHIPOperationalCredentialsDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2C1B02782641DB4E00780EF1 /* CHIPOperationalCredentialsDelegate.mm */; };
2C1B027B2641DB4E00780EF1 /* CHIPOperationalCredentialsDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C1B02792641DB4E00780EF1 /* CHIPOperationalCredentialsDelegate.h */; };
2C222AD0255C620600E446B9 /* CHIPDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C222ACE255C620600E446B9 /* CHIPDevice.h */; settings = {ATTRIBUTES = (Public, ); }; };
Expand Down Expand Up @@ -125,7 +124,6 @@
1ED276DF26C57CF000547A89 /* CHIPCallbackBridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = CHIPCallbackBridge.mm; path = "zap-generated/CHIPCallbackBridge.mm"; sourceTree = "<group>"; };
1ED276E126C5812A00547A89 /* CHIPCluster.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CHIPCluster.mm; sourceTree = "<group>"; };
1ED276E326C5832500547A89 /* CHIPCluster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHIPCluster.h; sourceTree = "<group>"; };
1EF9009E273AC39C006A4018 /* CHIPClustersInvoke.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CHIPClustersInvoke.cpp; path = "../../../../zzz_generated/controller-clusters/zap-generated/CHIPClustersInvoke.cpp"; sourceTree = "<group>"; };
2C1B02782641DB4E00780EF1 /* CHIPOperationalCredentialsDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CHIPOperationalCredentialsDelegate.mm; sourceTree = "<group>"; };
2C1B02792641DB4E00780EF1 /* CHIPOperationalCredentialsDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHIPOperationalCredentialsDelegate.h; sourceTree = "<group>"; };
2C222ACE255C620600E446B9 /* CHIPDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHIPDevice.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -224,7 +222,6 @@
1EC4CE5825CC26AB00D7304F /* CHIPGeneratedFiles */ = {
isa = PBXGroup;
children = (
1EF9009E273AC39C006A4018 /* CHIPClustersInvoke.cpp */,
1EC3238C271999E2002A8BF0 /* cluster-objects.cpp */,
1E16A8F926B9835600683C53 /* CHIPTestClustersObjc.h */,
1E16A8FA26B9835700683C53 /* CHIPTestClustersObjc.mm */,
Expand Down Expand Up @@ -520,7 +517,6 @@
B2E0D7B6245B0B5C003C5B48 /* CHIPManualSetupPayloadParser.mm in Sources */,
1E85732826551A490050A4D9 /* attribute-table.cpp in Sources */,
1E85732626551A490050A4D9 /* attribute-storage.cpp in Sources */,
1EF900A0273AC39C006A4018 /* CHIPClustersInvoke.cpp in Sources */,
1E85732C26551A490050A4D9 /* DataModelHandler.cpp in Sources */,
1E85733126551A490050A4D9 /* chip-message-send.cpp in Sources */,
1E85730F265519AE0050A4D9 /* attribute-size.cpp in Sources */,
Expand Down

This file was deleted.

18 changes: 0 additions & 18 deletions zzz_generated/bridge-app/zap-generated/CHIPClustersInvoke.cpp

This file was deleted.

Loading

0 comments on commit 14eaa07

Please sign in to comment.