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 <bzbarsky@apple.com>

---------

Co-authored-by: Restyled.io <commits@restyled.io>
Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>
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 51a5ab5..54d78c5 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 @@
     ~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 06fffda..f8acce6 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 @@
     ~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 3e28416..b8e7e13 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 @@
     ~RvcRunModeDelegate() override = default;
 };
 
+void Shutdown();
+
 } // namespace RvcRunMode
 
 namespace RvcCleanMode {
@@ -107,6 +109,8 @@
     ~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 7294fac..dcd9024 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 @@
     ~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 845ecb6..c96ec29 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 @@
     return CHIP_NO_ERROR;
 }
 
+void DishwasherMode::Shutdown()
+{
+    if (gDishwasherModeInstance != nullptr)
+    {
+        delete gDishwasherModeInstance;
+        gDishwasherModeInstance = nullptr;
+    }
+    if (gDishwasherModeDelegate != nullptr)
+    {
+        gDishwasherModeDelegate->~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 3cc44de..9d05b4b 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 @@
     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 36a2fd7..9a95054 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 @@
     return CHIP_NO_ERROR;
 }
 
+void RvcRunMode::Shutdown()
+{
+    if (gRvcRunModeInstance != nullptr)
+    {
+        delete gRvcRunModeInstance;
+        gRvcRunModeInstance = nullptr;
+    }
+    if (gRvcRunModeDelegate != nullptr)
+    {
+        gRvcRunModeDelegate->~RvcRunModeDelegate();
+    }
+}
+
 void emberAfRvcRunModeClusterInitCallback(chip::EndpointId endpointId)
 {
     VerifyOrDie(endpointId == 1); // this cluster is only enabled for endpoint 1.
@@ -158,6 +171,19 @@
     return CHIP_NO_ERROR;
 }
 
+void RvcCleanMode::Shutdown()
+{
+    if (gRvcCleanModeInstance != nullptr)
+    {
+        delete gRvcCleanModeInstance;
+        gRvcCleanModeInstance = nullptr;
+    }
+    if (gRvcCleanModeDelegate != nullptr)
+    {
+        gRvcCleanModeDelegate->~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 704e5b1..30b8c03 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 @@
     return CHIP_NO_ERROR;
 }
 
+void RefrigeratorAndTemperatureControlledCabinetMode::Shutdown()
+{
+    if (gTccModeInstance != nullptr)
+    {
+        delete gTccModeInstance;
+        gTccModeInstance = nullptr;
+    }
+    if (gTccModeDelegate != nullptr)
+    {
+        gTccModeDelegate->~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 0ebeff4..727bddb 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 @@
     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 d6e076b..0000000
--- 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 c9d829b..cd1e88c 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 @@
     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 b7e3a50..e3e8aa7 100644
--- a/examples/all-clusters-app/tizen/src/main.cpp
+++ b/examples/all-clusters-app/tizen/src/main.cpp
@@ -51,6 +51,8 @@
     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 698e140..a6fd0a9 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 @@
 
 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 adeb873..3276239 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 @@
     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 382ff7f..32930d7 100644
--- a/examples/bridge-app/linux/main.cpp
+++ b/examples/bridge-app/linux/main.cpp
@@ -741,6 +741,8 @@
 
 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 57e5273..9b15ae9 100644
--- a/examples/chef/linux/main.cpp
+++ b/examples/chef/linux/main.cpp
@@ -32,6 +32,8 @@
 
 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 b72cd7f..fcc56d7 100644
--- a/examples/contact-sensor-app/linux/main.cpp
+++ b/examples/contact-sensor-app/linux/main.cpp
@@ -33,6 +33,8 @@
 
 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 080df31..54e320f 100644
--- a/examples/dishwasher-app/linux/main.cpp
+++ b/examples/dishwasher-app/linux/main.cpp
@@ -32,6 +32,8 @@
     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 5689a0c..3bd27fd 100644
--- a/examples/lighting-app/linux/main.cpp
+++ b/examples/lighting-app/linux/main.cpp
@@ -85,7 +85,7 @@
     }
 }
 
-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 e69bc25..8f0bafa 100644
--- a/examples/lighting-app/tizen/src/main.cpp
+++ b/examples/lighting-app/tizen/src/main.cpp
@@ -52,6 +52,8 @@
 #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 5031fda..bf4f485 100644
--- a/examples/lock-app/linux/main.cpp
+++ b/examples/lock-app/linux/main.cpp
@@ -43,6 +43,8 @@
     }
 }
 
+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 71b8630..15d8ecd 100644
--- a/examples/ota-provider-app/linux/main.cpp
+++ b/examples/ota-provider-app/linux/main.cpp
@@ -380,6 +380,8 @@
     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 355f5c2..50cf241 100644
--- a/examples/ota-requestor-app/linux/main.cpp
+++ b/examples/ota-requestor-app/linux/main.cpp
@@ -255,6 +255,8 @@
     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 610e7b6..11f7529 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 ac97e61..22ff4d2 100644
--- a/examples/platform/linux/AppMain.cpp
+++ b/examples/platform/linux/AppMain.cpp
@@ -578,6 +578,8 @@
     }
     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 759b5da..94bf4d3 100644
--- a/examples/platform/linux/AppMain.h
+++ b/examples/platform/linux/AppMain.h
@@ -103,3 +103,6 @@
 
 // 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 6e515b7..dd6e123 100644
--- a/examples/resource-monitoring-app/linux/src/main.cpp
+++ b/examples/resource-monitoring-app/linux/src/main.cpp
@@ -48,6 +48,8 @@
     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 c039b4c..77de930 100644
--- a/examples/thermostat/linux/main.cpp
+++ b/examples/thermostat/linux/main.cpp
@@ -71,6 +71,8 @@
 
 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 ffdd5e0..859b3f4 100644
--- a/examples/tv-app/linux/main.cpp
+++ b/examples/tv-app/linux/main.cpp
@@ -47,6 +47,8 @@
     // emberAfEndpointEnableDisable(3, false);
 }
 
+void ApplicationShutdown() {}
+
 int main(int argc, char * argv[])
 {