From 39620532d40d01ab2f96a2768586920a7e912edb Mon Sep 17 00:00:00 2001 From: William Date: Tue, 25 Jul 2023 11:07:22 +0100 Subject: [PATCH] Replaced the use of std::set with IntrusiveList in ModeBase. (#28163) * Replaced the use of std::set with IntrusiveList in ModeBase. * Removed the std::set exeption for ModeBase. * Restyled by clang-format * Refoctor from review. * Added a way to gracefully shutdown the ModeBase dreived clusters and used it in the linux all-clusters-app. * Restyled by whitespace * Restyled by clang-format * Implemented required ApplicationExit(). * Restyled by clang-format * Modified the ModeBase example shutdowns to be safe if Shutdown is called twice and properly free the memory. * Renamed ApplicationExit() to ApplicationShutdown() * Apply documentation suggestions from code review Co-authored-by: Boris Zbarsky --------- Co-authored-by: Restyled.io Co-authored-by: Boris Zbarsky --- .../include/dishwasher-mode.h | 2 ++ .../include/laundry-washer-mode.h | 2 ++ .../all-clusters-common/include/rvc-modes.h | 4 +++ .../all-clusters-common/include/tcc-mode.h | 2 ++ .../src/dishwasher-mode.cpp | 14 +++++++++- .../src/laundry-washer-mode.cpp | 13 ++++++++++ .../all-clusters-common/src/rvc-modes.cpp | 26 +++++++++++++++++++ .../all-clusters-common/src/tcc-mode.cpp | 13 ++++++++++ .../all-clusters-app/linux/main-common.cpp | 10 +++++-- examples/all-clusters-app/linux/main-common.h | 21 --------------- examples/all-clusters-app/linux/main.cpp | 2 -- examples/all-clusters-app/tizen/src/main.cpp | 2 ++ .../linux/main-common.cpp | 2 ++ .../tizen/src/main.cpp | 2 ++ examples/bridge-app/linux/main.cpp | 2 ++ examples/chef/linux/main.cpp | 2 ++ examples/contact-sensor-app/linux/main.cpp | 2 ++ examples/dishwasher-app/linux/main.cpp | 2 ++ examples/lighting-app/linux/main.cpp | 2 +- examples/lighting-app/tizen/src/main.cpp | 2 ++ examples/lock-app/linux/main.cpp | 2 ++ examples/ota-provider-app/linux/main.cpp | 2 ++ examples/ota-requestor-app/linux/main.cpp | 2 ++ examples/placeholder/linux/main.cpp | 2 ++ examples/platform/linux/AppMain.cpp | 2 ++ examples/platform/linux/AppMain.h | 3 +++ .../linux/src/main.cpp | 2 ++ examples/thermostat/linux/main.cpp | 2 ++ examples/tv-app/linux/main.cpp | 2 ++ scripts/tools/check_includes_config.py | 3 --- .../mode-base-server/mode-base-server.cpp | 22 ++++++++++++---- .../mode-base-server/mode-base-server.h | 21 ++++++++++++--- .../clusters/on-off-server/on-off-server.cpp | 10 +++---- 33 files changed, 158 insertions(+), 44 deletions(-) delete mode 100644 examples/all-clusters-app/linux/main-common.h diff --git a/examples/all-clusters-app/all-clusters-common/include/dishwasher-mode.h b/examples/all-clusters-app/all-clusters-common/include/dishwasher-mode.h index 51a5ab5d0d80d8..54d78c56b23132 100644 --- a/examples/all-clusters-app/all-clusters-common/include/dishwasher-mode.h +++ b/examples/all-clusters-app/all-clusters-common/include/dishwasher-mode.h @@ -69,6 +69,8 @@ class DishwasherModeDelegate : public ModeBase::Delegate ~DishwasherModeDelegate() override = default; }; +void Shutdown(); + } // namespace DishwasherMode } // namespace Clusters diff --git a/examples/all-clusters-app/all-clusters-common/include/laundry-washer-mode.h b/examples/all-clusters-app/all-clusters-common/include/laundry-washer-mode.h index 06fffda82d99b1..f8acce69295f46 100644 --- a/examples/all-clusters-app/all-clusters-common/include/laundry-washer-mode.h +++ b/examples/all-clusters-app/all-clusters-common/include/laundry-washer-mode.h @@ -74,6 +74,8 @@ class LaundryWasherModeDelegate : public ModeBase::Delegate ~LaundryWasherModeDelegate() override = default; }; +void Shutdown(); + } // namespace LaundryWasherMode } // namespace Clusters diff --git a/examples/all-clusters-app/all-clusters-common/include/rvc-modes.h b/examples/all-clusters-app/all-clusters-common/include/rvc-modes.h index 3e2841654fb5e5..b8e7e13cf2c6ee 100644 --- a/examples/all-clusters-app/all-clusters-common/include/rvc-modes.h +++ b/examples/all-clusters-app/all-clusters-common/include/rvc-modes.h @@ -66,6 +66,8 @@ class RvcRunModeDelegate : public ModeBase::Delegate ~RvcRunModeDelegate() override = default; }; +void Shutdown(); + } // namespace RvcRunMode namespace RvcCleanMode { @@ -107,6 +109,8 @@ class RvcCleanModeDelegate : public ModeBase::Delegate ~RvcCleanModeDelegate() override = default; }; +void Shutdown(); + } // namespace RvcCleanMode } // namespace Clusters diff --git a/examples/all-clusters-app/all-clusters-common/include/tcc-mode.h b/examples/all-clusters-app/all-clusters-common/include/tcc-mode.h index 7294fac8cbccd8..dcd9024e8d0385 100644 --- a/examples/all-clusters-app/all-clusters-common/include/tcc-mode.h +++ b/examples/all-clusters-app/all-clusters-common/include/tcc-mode.h @@ -67,6 +67,8 @@ class TccModeDelegate : public ModeBase::Delegate ~TccModeDelegate() override = default; }; +void Shutdown(); + } // namespace RefrigeratorAndTemperatureControlledCabinetMode } // namespace Clusters diff --git a/examples/all-clusters-app/all-clusters-common/src/dishwasher-mode.cpp b/examples/all-clusters-app/all-clusters-common/src/dishwasher-mode.cpp index 845ecb6d32a8a9..c96ec297a2e2d2 100644 --- a/examples/all-clusters-app/all-clusters-common/src/dishwasher-mode.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/dishwasher-mode.cpp @@ -76,12 +76,24 @@ CHIP_ERROR DishwasherModeDelegate::GetModeTagsByIndex(uint8_t modeIndex, List~DishwasherModeDelegate(); + } +} + void emberAfDishwasherModeClusterInitCallback(chip::EndpointId endpointId) { VerifyOrDie(endpointId == 1); // this cluster is only enabled for endpoint 1. VerifyOrDie(gDishwasherModeDelegate == nullptr && gDishwasherModeInstance == nullptr); gDishwasherModeDelegate = new DishwasherMode::DishwasherModeDelegate; - // todo use Clusters::XxxMode::Feature::kXxxx to set features. gDishwasherModeInstance = new ModeBase::Instance(gDishwasherModeDelegate, 0x1, DishwasherMode::Id, chip::to_underlying(Feature::kOnOff)); gDishwasherModeInstance->Init(); diff --git a/examples/all-clusters-app/all-clusters-common/src/laundry-washer-mode.cpp b/examples/all-clusters-app/all-clusters-common/src/laundry-washer-mode.cpp index 3cc44deee84878..9d05b4b58850e0 100644 --- a/examples/all-clusters-app/all-clusters-common/src/laundry-washer-mode.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/laundry-washer-mode.cpp @@ -75,6 +75,19 @@ CHIP_ERROR LaundryWasherModeDelegate::GetModeTagsByIndex(uint8_t modeIndex, List return CHIP_NO_ERROR; } +void LaundryWasherMode::Shutdown() +{ + if (gLaundryWasherModeInstance != nullptr) + { + delete gLaundryWasherModeInstance; + gLaundryWasherModeInstance = nullptr; + } + if (gLaundryWasherModeDelegate != nullptr) + { + gLaundryWasherModeDelegate->~LaundryWasherModeDelegate(); + } +} + void emberAfLaundryWasherModeClusterInitCallback(chip::EndpointId endpointId) { VerifyOrDie(endpointId == 1); // this cluster is only enabled for endpoint 1. diff --git a/examples/all-clusters-app/all-clusters-common/src/rvc-modes.cpp b/examples/all-clusters-app/all-clusters-common/src/rvc-modes.cpp index 36a2fd7204a77c..9a95054c26f8ab 100644 --- a/examples/all-clusters-app/all-clusters-common/src/rvc-modes.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/rvc-modes.cpp @@ -88,6 +88,19 @@ CHIP_ERROR RvcRunModeDelegate::GetModeTagsByIndex(uint8_t modeIndex, List~RvcRunModeDelegate(); + } +} + void emberAfRvcRunModeClusterInitCallback(chip::EndpointId endpointId) { VerifyOrDie(endpointId == 1); // this cluster is only enabled for endpoint 1. @@ -158,6 +171,19 @@ CHIP_ERROR RvcCleanModeDelegate::GetModeTagsByIndex(uint8_t modeIndex, List~RvcCleanModeDelegate(); + } +} + void emberAfRvcCleanModeClusterInitCallback(chip::EndpointId endpointId) { VerifyOrDie(endpointId == 1); // this cluster is only enabled for endpoint 1. diff --git a/examples/all-clusters-app/all-clusters-common/src/tcc-mode.cpp b/examples/all-clusters-app/all-clusters-common/src/tcc-mode.cpp index 704e5b17be22cb..30b8c03075e2ea 100644 --- a/examples/all-clusters-app/all-clusters-common/src/tcc-mode.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/tcc-mode.cpp @@ -75,6 +75,19 @@ CHIP_ERROR TccModeDelegate::GetModeTagsByIndex(uint8_t modeIndex, List~TccModeDelegate(); + } +} + void emberAfRefrigeratorAndTemperatureControlledCabinetModeClusterInitCallback(chip::EndpointId endpointId) { VerifyOrDie(endpointId == 1); // this cluster is only enabled for endpoint 1. diff --git a/examples/all-clusters-app/linux/main-common.cpp b/examples/all-clusters-app/linux/main-common.cpp index 0ebeff439e9dc2..727bddb955056b 100644 --- a/examples/all-clusters-app/linux/main-common.cpp +++ b/examples/all-clusters-app/linux/main-common.cpp @@ -16,7 +16,6 @@ * limitations under the License. */ -#include "main-common.h" #include "AllClustersCommandDelegate.h" #include "WindowCoveringManager.h" #include "dishwasher-mode.h" @@ -191,8 +190,15 @@ void ApplicationInit() app::Clusters::TemperatureControl::SetInstance(&sAppSupportedTemperatureLevelsDelegate); } -void ApplicationExit() +void ApplicationShutdown() { + // These may have been initialised via the emberAfXxxClusterInitCallback methods. We need to destroy them before shutdown. + Clusters::DishwasherMode::Shutdown(); + Clusters::LaundryWasherMode::Shutdown(); + Clusters::RvcCleanMode::Shutdown(); + Clusters::RvcRunMode::Shutdown(); + Clusters::RefrigeratorAndTemperatureControlledCabinetMode::Shutdown(); + if (sChipNamedPipeCommands.Stop() != CHIP_NO_ERROR) { ChipLogError(NotSpecified, "Failed to stop CHIP NamedPipeCommands"); diff --git a/examples/all-clusters-app/linux/main-common.h b/examples/all-clusters-app/linux/main-common.h deleted file mode 100644 index d6e076b4416798..00000000000000 --- a/examples/all-clusters-app/linux/main-common.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * - * Copyright (c) 2022 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 - -void ApplicationExit(); diff --git a/examples/all-clusters-app/linux/main.cpp b/examples/all-clusters-app/linux/main.cpp index c9d829ba423e44..cd1e88c87e3108 100644 --- a/examples/all-clusters-app/linux/main.cpp +++ b/examples/all-clusters-app/linux/main.cpp @@ -19,7 +19,6 @@ #include "AppMain.h" #include "AppOptions.h" #include "binding-handler.h" -#include "main-common.h" // Network commissioning namespace { @@ -35,7 +34,6 @@ int main(int argc, char * argv[]) LinuxDeviceOptions::GetInstance().dacProvider = AppOptions::GetDACProvider(); ChipLinuxAppMainLoop(); - ApplicationExit(); return 0; } diff --git a/examples/all-clusters-app/tizen/src/main.cpp b/examples/all-clusters-app/tizen/src/main.cpp index b7e3a501df17b3..e3e8aa736846fc 100644 --- a/examples/all-clusters-app/tizen/src/main.cpp +++ b/examples/all-clusters-app/tizen/src/main.cpp @@ -51,6 +51,8 @@ void ApplicationInit() app::Clusters::TemperatureControl::SetInstance(&sAppSupportedTemperatureLevelsDelegate); } +void ApplicationShutdown() {} + int main(int argc, char * argv[]) { TizenServiceAppMain app; diff --git a/examples/all-clusters-minimal-app/linux/main-common.cpp b/examples/all-clusters-minimal-app/linux/main-common.cpp index 698e1400b8e2b7..a6fd0a9866220e 100644 --- a/examples/all-clusters-minimal-app/linux/main-common.cpp +++ b/examples/all-clusters-minimal-app/linux/main-common.cpp @@ -84,6 +84,8 @@ static Identify gIdentify1 = { void ApplicationInit() {} +void ApplicationShutdown() {} + void emberAfLowPowerClusterInitCallback(EndpointId endpoint) { ChipLogProgress(Zcl, "TV Linux App: LowPower::SetDefaultDelegate"); diff --git a/examples/all-clusters-minimal-app/tizen/src/main.cpp b/examples/all-clusters-minimal-app/tizen/src/main.cpp index adeb8735752332..327623911831bb 100644 --- a/examples/all-clusters-minimal-app/tizen/src/main.cpp +++ b/examples/all-clusters-minimal-app/tizen/src/main.cpp @@ -47,6 +47,8 @@ void ApplicationInit() sEthernetNetworkCommissioningInstance.Init(); } +void ApplicationShutdown(){}; + int main(int argc, char * argv[]) { TizenServiceAppMain app; diff --git a/examples/bridge-app/linux/main.cpp b/examples/bridge-app/linux/main.cpp index 382ff7fe456de0..32930d7133db77 100644 --- a/examples/bridge-app/linux/main.cpp +++ b/examples/bridge-app/linux/main.cpp @@ -741,6 +741,8 @@ bool emberAfActionsClusterInstantActionCallback(app::CommandHandler * commandObj void ApplicationInit() {} +void ApplicationShutdown() {} + const EmberAfDeviceType gBridgedOnOffDeviceTypes[] = { { DEVICE_TYPE_LO_ON_OFF_LIGHT, DEVICE_VERSION_DEFAULT }, { DEVICE_TYPE_BRIDGED_NODE, DEVICE_VERSION_DEFAULT } }; diff --git a/examples/chef/linux/main.cpp b/examples/chef/linux/main.cpp index 57e5273d5a58d2..9b15ae9cba6582 100644 --- a/examples/chef/linux/main.cpp +++ b/examples/chef/linux/main.cpp @@ -32,6 +32,8 @@ using namespace chip::app; void ApplicationInit() {} +void ApplicationShutdown() {} + int main(int argc, char * argv[]) { if (ChipLinuxAppInit(argc, argv) != 0) diff --git a/examples/contact-sensor-app/linux/main.cpp b/examples/contact-sensor-app/linux/main.cpp index b72cd7f755ab46..fcc56d7c3d02a4 100644 --- a/examples/contact-sensor-app/linux/main.cpp +++ b/examples/contact-sensor-app/linux/main.cpp @@ -33,6 +33,8 @@ using namespace chip::app::Clusters; void ApplicationInit() {} +void ApplicationShutdown() {} + int main(int argc, char * argv[]) { VerifyOrDie(ChipLinuxAppInit(argc, argv) == 0); diff --git a/examples/dishwasher-app/linux/main.cpp b/examples/dishwasher-app/linux/main.cpp index 080df313425cba..54e320ffc9e14c 100644 --- a/examples/dishwasher-app/linux/main.cpp +++ b/examples/dishwasher-app/linux/main.cpp @@ -32,6 +32,8 @@ void ApplicationInit() MatterOperationalStateServerInit(); } +void ApplicationShutdown() {} + int main(int argc, char * argv[]) { if (ChipLinuxAppInit(argc, argv) != 0) diff --git a/examples/lighting-app/linux/main.cpp b/examples/lighting-app/linux/main.cpp index 5689a0cd68979c..3bd27fddc0f95a 100644 --- a/examples/lighting-app/linux/main.cpp +++ b/examples/lighting-app/linux/main.cpp @@ -85,7 +85,7 @@ void ApplicationInit() } } -void ApplicationExit() +void ApplicationShutdown() { if (sChipNamedPipeCommands.Stop() != CHIP_NO_ERROR) { diff --git a/examples/lighting-app/tizen/src/main.cpp b/examples/lighting-app/tizen/src/main.cpp index e69bc25fdc1c7a..8f0bafaec72e31 100644 --- a/examples/lighting-app/tizen/src/main.cpp +++ b/examples/lighting-app/tizen/src/main.cpp @@ -52,6 +52,8 @@ void ApplicationInit() #endif } +void ApplicationShutdown() {} + int main(int argc, char * argv[]) { TizenServiceAppMain app; diff --git a/examples/lock-app/linux/main.cpp b/examples/lock-app/linux/main.cpp index 5031fda7db3755..bf4f485758485a 100644 --- a/examples/lock-app/linux/main.cpp +++ b/examples/lock-app/linux/main.cpp @@ -43,6 +43,8 @@ void ApplicationInit() } } +void ApplicationShutdown() {} + int main(int argc, char * argv[]) { VerifyOrDie(ChipLinuxAppInit(argc, argv) == 0); diff --git a/examples/ota-provider-app/linux/main.cpp b/examples/ota-provider-app/linux/main.cpp index 71b8630cdb2e48..15d8ecdf55feea 100644 --- a/examples/ota-provider-app/linux/main.cpp +++ b/examples/ota-provider-app/linux/main.cpp @@ -380,6 +380,8 @@ void ApplicationInit() chip::app::Clusters::OTAProvider::SetDelegate(kOtaProviderEndpoint, &gOtaProvider); } +void ApplicationShutdown() {} + int main(int argc, char * argv[]) { VerifyOrDie(ChipLinuxAppInit(argc, argv, &cmdLineOptions) == 0); diff --git a/examples/ota-requestor-app/linux/main.cpp b/examples/ota-requestor-app/linux/main.cpp index 355f5c2c133e87..50cf24191a5a98 100644 --- a/examples/ota-requestor-app/linux/main.cpp +++ b/examples/ota-requestor-app/linux/main.cpp @@ -255,6 +255,8 @@ void ApplicationInit() InitOTARequestor(); } +void ApplicationShutdown() {} + int main(int argc, char * argv[]) { VerifyOrDie(ChipLinuxAppInit(argc, argv, &cmdLineOptions, MakeOptional(kNetworkCommissioningEndpointSecondary)) == 0); diff --git a/examples/placeholder/linux/main.cpp b/examples/placeholder/linux/main.cpp index 610e7b65dc1ae3..11f7529e07aa03 100644 --- a/examples/placeholder/linux/main.cpp +++ b/examples/placeholder/linux/main.cpp @@ -22,6 +22,8 @@ void ApplicationInit() {} +void ApplicationShutdown() {} + int main(int argc, char * argv[]) { VerifyOrDie(ChipLinuxAppInit(argc, argv, AppOptions::GetOptions()) == 0); diff --git a/examples/platform/linux/AppMain.cpp b/examples/platform/linux/AppMain.cpp index ac97e6104417b3..22ff4d2db71cb6 100644 --- a/examples/platform/linux/AppMain.cpp +++ b/examples/platform/linux/AppMain.cpp @@ -578,6 +578,8 @@ void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl) } gMainLoopImplementation = nullptr; + ApplicationShutdown(); + #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE ShutdownCommissioner(); #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE diff --git a/examples/platform/linux/AppMain.h b/examples/platform/linux/AppMain.h index 759b5da6eb4b3f..94bf4d3e609da1 100644 --- a/examples/platform/linux/AppMain.h +++ b/examples/platform/linux/AppMain.h @@ -103,3 +103,6 @@ CommissionerDiscoveryController * GetCommissionerDiscoveryController(); // For extra init calls, the function will be called right before running Matter main loop. void ApplicationInit(); + +// For extra shutdown calls, the function will be called before any of the core Matter objects are shut down. +void ApplicationShutdown(); diff --git a/examples/resource-monitoring-app/linux/src/main.cpp b/examples/resource-monitoring-app/linux/src/main.cpp index 6e515b7ea5845c..dd6e1231d6a9e2 100644 --- a/examples/resource-monitoring-app/linux/src/main.cpp +++ b/examples/resource-monitoring-app/linux/src/main.cpp @@ -48,6 +48,8 @@ void ApplicationInit() gActivatedCarbonFilterInstance.Init(); } +void ApplicationShutdown() {} + int main(int argc, char * argv[]) { if (ChipLinuxAppInit(argc, argv) != 0) diff --git a/examples/thermostat/linux/main.cpp b/examples/thermostat/linux/main.cpp index c039b4cd1902d5..77de93055e3aa0 100644 --- a/examples/thermostat/linux/main.cpp +++ b/examples/thermostat/linux/main.cpp @@ -71,6 +71,8 @@ static Identify gIdentify1 = { void ApplicationInit() {} +void ApplicationShutdown() {} + int main(int argc, char * argv[]) { VerifyOrDie(ChipLinuxAppInit(argc, argv) == 0); diff --git a/examples/tv-app/linux/main.cpp b/examples/tv-app/linux/main.cpp index ffdd5e00bc5513..859b3f47284929 100644 --- a/examples/tv-app/linux/main.cpp +++ b/examples/tv-app/linux/main.cpp @@ -47,6 +47,8 @@ void ApplicationInit() // emberAfEndpointEnableDisable(3, false); } +void ApplicationShutdown() {} + int main(int argc, char * argv[]) { diff --git a/scripts/tools/check_includes_config.py b/scripts/tools/check_includes_config.py index fba3a095e74a6d..cb1f4e1062fb26 100644 --- a/scripts/tools/check_includes_config.py +++ b/scripts/tools/check_includes_config.py @@ -158,7 +158,4 @@ # Library meant for non-embedded 'src/tracing/json/json_tracing.cpp': {'string', 'sstream'}, 'src/tracing/json/json_tracing.h': {'fstream'}, - - # Temporary solution util the OnOff server can provide a callback API for state change. - 'src/app/clusters/mode-base-server/mode-base-server.h': {'set'} } diff --git a/src/app/clusters/mode-base-server/mode-base-server.cpp b/src/app/clusters/mode-base-server/mode-base-server.cpp index ac85ccb9941ec9..f4ec6a46ec7581 100644 --- a/src/app/clusters/mode-base-server/mode-base-server.cpp +++ b/src/app/clusters/mode-base-server/mode-base-server.cpp @@ -38,6 +38,19 @@ namespace app { namespace Clusters { namespace ModeBase { +void Instance::RegisterInstance() +{ + if (!gModeBaseAliasesInstances.Contains(this)) + { + gModeBaseAliasesInstances.PushBack(this); + } +} + +void Instance::UnregisterInstance() +{ + gModeBaseAliasesInstances.Remove(this); +} + bool Instance::HasFeature(Feature feature) const { return (mFeature & to_underlying(feature)) != 0; @@ -137,10 +150,9 @@ CHIP_ERROR Instance::Init() ReturnErrorOnFailure(chip::app::InteractionModelEngine::GetInstance()->RegisterCommandHandler(this)); VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE); + RegisterInstance(); ReturnErrorOnFailure(mDelegate->Init()); - ModeBaseAliasesInstances.insert(this); - // If the StartUpMode is set, the CurrentMode attribute SHALL be set to the StartUpMode value, when the server is powered up. if (!mStartUpMode.IsNull()) { @@ -476,14 +488,14 @@ Instance::Instance(Delegate * aDelegate, EndpointId aEndpointId, ClusterId aClus Instance::~Instance() { - ModeBaseAliasesInstances.erase(this); + UnregisterInstance(); chip::app::InteractionModelEngine::GetInstance()->UnregisterCommandHandler(this); unregisterAttributeAccessOverride(this); } -std::set * GetModeBaseInstances() +IntrusiveList & GetModeBaseInstanceList() { - return &ModeBaseAliasesInstances; + return gModeBaseAliasesInstances; } } // namespace ModeBase diff --git a/src/app/clusters/mode-base-server/mode-base-server.h b/src/app/clusters/mode-base-server/mode-base-server.h index 617fd262ba8515..3e1b77bcbf7e2a 100644 --- a/src/app/clusters/mode-base-server/mode-base-server.h +++ b/src/app/clusters/mode-base-server/mode-base-server.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include namespace chip { namespace app { @@ -32,7 +32,7 @@ namespace ModeBase { class Delegate; -class Instance : public CommandHandlerInterface, public AttributeAccessInterface +class Instance : public CommandHandlerInterface, public AttributeAccessInterface, public IntrusiveListNodeBase<> { private: Delegate * mDelegate; @@ -55,6 +55,16 @@ class Instance : public CommandHandlerInterface, public AttributeAccessInterface CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; CHIP_ERROR Write(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder) override; + /** + * Register this ModeBase instance. + */ + void RegisterInstance(); + + /** + * Unregister this ModeBase instance. + */ + void UnregisterInstance(); + /** * Internal change-to-mode command handler function. */ @@ -229,9 +239,12 @@ class Delegate // A set of pointers to all initialised ModeBase instances. It provides a way to access all ModeBase derived clusters. // todo change once there is a clear public interface for the OnOff cluster data dependencies (#27508) -static std::set ModeBaseAliasesInstances; +static IntrusiveList gModeBaseAliasesInstances; -std::set * GetModeBaseInstances(); +// This does not return a refernce to const IntrusiveList, because the caller might need +// to change the state of the instances in the list and const IntrusiveList only allows +// access to const Instance. +IntrusiveList & GetModeBaseInstanceList(); } // namespace ModeBase } // namespace Clusters diff --git a/src/app/clusters/on-off-server/on-off-server.cpp b/src/app/clusters/on-off-server/on-off-server.cpp index eb1c320b800da6..440ea0a471fa30 100644 --- a/src/app/clusters/on-off-server/on-off-server.cpp +++ b/src/app/clusters/on-off-server/on-off-server.cpp @@ -60,16 +60,16 @@ namespace { */ void UpdateModeBaseCurrentModeToOnMode(EndpointId endpoint) { - for (const auto & modeBaseInstance : *ModeBase::GetModeBaseInstances()) + for (auto & modeBaseInstance : ModeBase::GetModeBaseInstanceList()) { - if (modeBaseInstance->GetEndpointId() == endpoint) + if (modeBaseInstance.GetEndpointId() == endpoint) { - if (modeBaseInstance->HasFeature(ModeBase::Feature::kOnOff)) + if (modeBaseInstance.HasFeature(ModeBase::Feature::kOnOff)) { - ModeBase::Attributes::OnMode::TypeInfo::Type onMode = modeBaseInstance->GetOnMode(); + ModeBase::Attributes::OnMode::TypeInfo::Type onMode = modeBaseInstance.GetOnMode(); if (!onMode.IsNull()) { - Status status = modeBaseInstance->UpdateCurrentMode(onMode.Value()); + Status status = modeBaseInstance.UpdateCurrentMode(onMode.Value()); if (status == Status::Success) { ChipLogProgress(Zcl, "Changed the Current Mode to %x", onMode.Value());