diff --git a/src/app/MessageDef/MessageDefHelper.cpp b/src/app/MessageDef/MessageDefHelper.cpp index 717519080ddde5..112d99cf5ca2de 100644 --- a/src/app/MessageDef/MessageDefHelper.cpp +++ b/src/app/MessageDef/MessageDefHelper.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -37,26 +38,27 @@ namespace app { // this is used to run in signle thread for IM message debug purpose namespace { uint32_t gPrettyPrintingDepthLevel = 0; -char gLineBuffer[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE]; +Global gLineBuffer; size_t gCurLineBufferSize = 0; } // namespace void PrettyPrintIMBlankLine() { + char * lineBuffer = gLineBuffer.get(); if (gCurLineBufferSize) { // Don't need to explicitly NULL-terminate the string because // snprintf takes care of that. - ChipLogDetail(DataManagement, "%s", gLineBuffer); + ChipLogDetail(DataManagement, "%s", lineBuffer); gCurLineBufferSize = 0; } for (uint32_t i = 0; i < gPrettyPrintingDepthLevel; i++) { - if (sizeof(gLineBuffer) > gCurLineBufferSize) + if (CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE > gCurLineBufferSize) { - size_t sizeLeft = sizeof(gLineBuffer) - gCurLineBufferSize; - size_t ret = (size_t) (snprintf(gLineBuffer + gCurLineBufferSize, sizeLeft, "\t")); + size_t sizeLeft = CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE - gCurLineBufferSize; + size_t ret = (size_t) (snprintf(lineBuffer + gCurLineBufferSize, sizeLeft, "\t")); if (ret > 0) { gCurLineBufferSize += std::min(ret, sizeLeft); @@ -75,10 +77,10 @@ void PrettyPrintIM(bool aIsNewLine, const char * aFmt, ...) PrettyPrintIMBlankLine(); } - if (sizeof(gLineBuffer) > gCurLineBufferSize) + if (CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE > gCurLineBufferSize) { - size_t sizeLeft = sizeof(gLineBuffer) - gCurLineBufferSize; - size_t ret = (size_t) (vsnprintf(gLineBuffer + gCurLineBufferSize, sizeLeft, aFmt, args)); + size_t sizeLeft = CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE - gCurLineBufferSize; + size_t ret = (size_t) (vsnprintf(gLineBuffer.get() + gCurLineBufferSize, sizeLeft, aFmt, args)); if (ret > 0) { gCurLineBufferSize += std::min(ret, sizeLeft); diff --git a/src/app/reporting/ReportScheduler.h b/src/app/reporting/ReportScheduler.h index d6425e34818c9a..5d65b1a7f04101 100644 --- a/src/app/reporting/ReportScheduler.h +++ b/src/app/reporting/ReportScheduler.h @@ -190,10 +190,17 @@ class ReportScheduler : public ReadHandler::Observer, public ICDStateObserver BitFlags mFlags; }; + ReportScheduler() : mTimerDelegate(nullptr) {} ReportScheduler(TimerDelegate * aTimerDelegate) : mTimerDelegate(aTimerDelegate) {} virtual ~ReportScheduler() = default; + void Init(TimerDelegate * aTimerDelegate) + { + mTimerDelegate = aTimerDelegate; + VerifyOrDie(nullptr != mTimerDelegate); + } + virtual void ReportTimerCallback() = 0; /// @brief Check whether a ReadHandler is reportable right now, taking into account its minimum and maximum intervals. diff --git a/src/app/reporting/ReportSchedulerImpl.cpp b/src/app/reporting/ReportSchedulerImpl.cpp index f50d7498b0f4b8..18e6bedea6b3df 100644 --- a/src/app/reporting/ReportSchedulerImpl.cpp +++ b/src/app/reporting/ReportSchedulerImpl.cpp @@ -33,11 +33,6 @@ void ReportSchedulerImpl::ReportTimerCallback() InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun(); } -ReportSchedulerImpl::ReportSchedulerImpl(TimerDelegate * aTimerDelegate) : ReportScheduler(aTimerDelegate) -{ - VerifyOrDie(nullptr != mTimerDelegate); -} - /// @brief Method that triggers a report emission on each ReadHandler that is not blocked on its min interval. /// Each read handler that is not blocked is immediately marked dirty so that it will report as soon as possible. void ReportSchedulerImpl::OnEnterActiveMode() diff --git a/src/app/reporting/ReportSchedulerImpl.h b/src/app/reporting/ReportSchedulerImpl.h index f7889a5ac3e6c7..87a1f7f4faa555 100644 --- a/src/app/reporting/ReportSchedulerImpl.h +++ b/src/app/reporting/ReportSchedulerImpl.h @@ -62,7 +62,8 @@ class ReportSchedulerImpl : public ReportScheduler public: using Timeout = System::Clock::Timeout; - ReportSchedulerImpl(TimerDelegate * aTimerDelegate); + ReportSchedulerImpl() = default; + ReportSchedulerImpl(TimerDelegate * aTimerDelegate) : ReportScheduler(aTimerDelegate) {} ~ReportSchedulerImpl() override { UnregisterAllHandlers(); } // ICDStateObserver diff --git a/src/app/reporting/SynchronizedReportSchedulerImpl.h b/src/app/reporting/SynchronizedReportSchedulerImpl.h index b0016204849dcd..84fe9da1bd2fb2 100644 --- a/src/app/reporting/SynchronizedReportSchedulerImpl.h +++ b/src/app/reporting/SynchronizedReportSchedulerImpl.h @@ -79,6 +79,7 @@ class SynchronizedReportSchedulerImpl : public ReportSchedulerImpl, public Timer public: void OnReadHandlerDestroyed(ReadHandler * aReadHandler) override; + SynchronizedReportSchedulerImpl() = default; SynchronizedReportSchedulerImpl(TimerDelegate * aTimerDelegate) : ReportSchedulerImpl(aTimerDelegate) {} ~SynchronizedReportSchedulerImpl() override { UnregisterAllHandlers(); } diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index cfb8d21de3a130..c3959ca6d305cc 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -104,15 +105,15 @@ class DeviceTypeResolver : public chip::Access::AccessControl::DeviceTypeResolve namespace chip { -Server Server::sServer; +Global Server::sServer; #if CHIP_CONFIG_ENABLE_SERVER_IM_EVENT #define CHIP_NUM_EVENT_LOGGING_BUFFERS 3 -static uint8_t sInfoEventBuffer[CHIP_DEVICE_CONFIG_EVENT_LOGGING_INFO_BUFFER_SIZE]; -static uint8_t sDebugEventBuffer[CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE]; -static uint8_t sCritEventBuffer[CHIP_DEVICE_CONFIG_EVENT_LOGGING_CRIT_BUFFER_SIZE]; -static ::chip::PersistedCounter sGlobalEventIdCounter; -static ::chip::app::CircularEventBuffer sLoggingBuffer[CHIP_NUM_EVENT_LOGGING_BUFFERS]; +static Global sInfoEventBuffer; +static Global sDebugEventBuffer; +static Global sCritEventBuffer; +static Global<::chip::PersistedCounter> sGlobalEventIdCounter; +static Global<::chip::app::CircularEventBuffer[CHIP_NUM_EVENT_LOGGING_BUFFERS]> sLoggingBuffer; #endif // CHIP_CONFIG_ENABLE_SERVER_IM_EVENT CHIP_ERROR Server::Init(const ServerInitParams & initParams) @@ -278,19 +279,19 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) #if CHIP_CONFIG_ENABLE_SERVER_IM_EVENT // Initialize event logging subsystem - err = sGlobalEventIdCounter.Init(mDeviceStorage, DefaultStorageKeyAllocator::IMEventNumber(), - CHIP_DEVICE_CONFIG_EVENT_ID_COUNTER_EPOCH); + err = sGlobalEventIdCounter->Init(mDeviceStorage, DefaultStorageKeyAllocator::IMEventNumber(), + CHIP_DEVICE_CONFIG_EVENT_ID_COUNTER_EPOCH); SuccessOrExit(err); { ::chip::app::LogStorageResources logStorageResources[] = { - { &sDebugEventBuffer[0], sizeof(sDebugEventBuffer), ::chip::app::PriorityLevel::Debug }, - { &sInfoEventBuffer[0], sizeof(sInfoEventBuffer), ::chip::app::PriorityLevel::Info }, - { &sCritEventBuffer[0], sizeof(sCritEventBuffer), ::chip::app::PriorityLevel::Critical } + { sDebugEventBuffer.get(), CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE, ::chip::app::PriorityLevel::Debug }, + { sInfoEventBuffer.get(), CHIP_DEVICE_CONFIG_EVENT_LOGGING_INFO_BUFFER_SIZE, ::chip::app::PriorityLevel::Info }, + { sCritEventBuffer.get(), CHIP_DEVICE_CONFIG_EVENT_LOGGING_CRIT_BUFFER_SIZE, ::chip::app::PriorityLevel::Critical } }; - chip::app::EventManagement::GetInstance().Init(&mExchangeMgr, CHIP_NUM_EVENT_LOGGING_BUFFERS, &sLoggingBuffer[0], - &logStorageResources[0], &sGlobalEventIdCounter, + chip::app::EventManagement::GetInstance().Init(&mExchangeMgr, CHIP_NUM_EVENT_LOGGING_BUFFERS, sLoggingBuffer.get(), + &logStorageResources[0], &sGlobalEventIdCounter.get(), std::chrono::duration_cast(mInitTimestamp)); } #endif // CHIP_CONFIG_ENABLE_SERVER_IM_EVENT @@ -787,23 +788,22 @@ void Server::ResumeSubscriptions() Credentials::IgnoreCertificateValidityPeriodPolicy Server::sDefaultCertValidityPolicy; -KvsPersistentStorageDelegate CommonCaseDeviceServerInitParams::sKvsPersistenStorageDelegate; -PersistentStorageOperationalKeystore CommonCaseDeviceServerInitParams::sPersistentStorageOperationalKeystore; -Credentials::PersistentStorageOpCertStore CommonCaseDeviceServerInitParams::sPersistentStorageOpCertStore; -Credentials::GroupDataProviderImpl CommonCaseDeviceServerInitParams::sGroupDataProvider; -app::DefaultTimerDelegate CommonCaseDeviceServerInitParams::sTimerDelegate; -app::reporting::ReportSchedulerImpl - CommonCaseDeviceServerInitParams::sReportScheduler(&CommonCaseDeviceServerInitParams::sTimerDelegate); +Global CommonCaseDeviceServerInitParams::sKvsPersistenStorageDelegate; +Global CommonCaseDeviceServerInitParams::sPersistentStorageOperationalKeystore; +Global CommonCaseDeviceServerInitParams::sPersistentStorageOpCertStore; +Global CommonCaseDeviceServerInitParams::sGroupDataProvider; +Global CommonCaseDeviceServerInitParams::sTimerDelegate; +Global CommonCaseDeviceServerInitParams::sReportScheduler; #if CHIP_CONFIG_ENABLE_SESSION_RESUMPTION -SimpleSessionResumptionStorage CommonCaseDeviceServerInitParams::sSessionResumptionStorage; +Global CommonCaseDeviceServerInitParams::sSessionResumptionStorage; #endif #if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS -app::SimpleSubscriptionResumptionStorage CommonCaseDeviceServerInitParams::sSubscriptionResumptionStorage; +Global CommonCaseDeviceServerInitParams::sSubscriptionResumptionStorage; #endif -app::DefaultAclStorage CommonCaseDeviceServerInitParams::sAclStorage; -Crypto::DefaultSessionKeystore CommonCaseDeviceServerInitParams::sSessionKeystore; +Global CommonCaseDeviceServerInitParams::sAclStorage; +Global CommonCaseDeviceServerInitParams::sSessionKeystore; #if CHIP_CONFIG_ENABLE_ICD_CIP -app::DefaultICDCheckInBackOffStrategy CommonCaseDeviceServerInitParams::sDefaultICDCheckInBackOffStrategy; +Global CommonCaseDeviceServerInitParams::sDefaultICDCheckInBackOffStrategy; #endif } // namespace chip diff --git a/src/app/server/Server.h b/src/app/server/Server.h index 2f61197fcee2dd..25ef25636eafeb 100644 --- a/src/app/server/Server.h +++ b/src/app/server/Server.h @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -241,8 +242,8 @@ struct CommonCaseDeviceServerInitParams : public ServerInitParams { chip::DeviceLayer::PersistedStorage::KeyValueStoreManager & kvsManager = DeviceLayer::PersistedStorage::KeyValueStoreMgr(); - ReturnErrorOnFailure(sKvsPersistenStorageDelegate.Init(&kvsManager)); - this->persistentStorageDelegate = &sKvsPersistenStorageDelegate; + ReturnErrorOnFailure(sKvsPersistenStorageDelegate->Init(&kvsManager)); + this->persistentStorageDelegate = &sKvsPersistenStorageDelegate.get(); } // PersistentStorageDelegate "software-based" operational key access injection @@ -250,8 +251,8 @@ struct CommonCaseDeviceServerInitParams : public ServerInitParams { // WARNING: PersistentStorageOperationalKeystore::Finish() is never called. It's fine for // for examples and for now. - ReturnErrorOnFailure(sPersistentStorageOperationalKeystore.Init(this->persistentStorageDelegate)); - this->operationalKeystore = &sPersistentStorageOperationalKeystore; + ReturnErrorOnFailure(sPersistentStorageOperationalKeystore->Init(this->persistentStorageDelegate)); + this->operationalKeystore = &sPersistentStorageOperationalKeystore.get(); } // OpCertStore can be injected but default to persistent storage default @@ -260,8 +261,8 @@ struct CommonCaseDeviceServerInitParams : public ServerInitParams { // WARNING: PersistentStorageOpCertStore::Finish() is never called. It's fine for // for examples and for now, since all storage is immediate for that impl. - ReturnErrorOnFailure(sPersistentStorageOpCertStore.Init(this->persistentStorageDelegate)); - this->opCertStore = &sPersistentStorageOpCertStore; + ReturnErrorOnFailure(sPersistentStorageOpCertStore->Init(this->persistentStorageDelegate)); + this->opCertStore = &sPersistentStorageOpCertStore.get(); } // Injection of report scheduler WILL lead to two schedulers being allocated. As recommended above, this should only be used @@ -269,21 +270,22 @@ struct CommonCaseDeviceServerInitParams : public ServerInitParams // CommonCaseDeviceServerInitParams should not be allocated. if (this->reportScheduler == nullptr) { - reportScheduler = &sReportScheduler; + sReportScheduler->Init(&sTimerDelegate.get()); + reportScheduler = &sReportScheduler.get(); } // Session Keystore injection - this->sessionKeystore = &sSessionKeystore; + this->sessionKeystore = &sSessionKeystore.get(); // Group Data provider injection - sGroupDataProvider.SetStorageDelegate(this->persistentStorageDelegate); - sGroupDataProvider.SetSessionKeystore(this->sessionKeystore); - ReturnErrorOnFailure(sGroupDataProvider.Init()); - this->groupDataProvider = &sGroupDataProvider; + sGroupDataProvider->SetStorageDelegate(this->persistentStorageDelegate); + sGroupDataProvider->SetSessionKeystore(this->sessionKeystore); + ReturnErrorOnFailure(sGroupDataProvider->Init()); + this->groupDataProvider = &sGroupDataProvider.get(); #if CHIP_CONFIG_ENABLE_SESSION_RESUMPTION - ReturnErrorOnFailure(sSessionResumptionStorage.Init(this->persistentStorageDelegate)); - this->sessionResumptionStorage = &sSessionResumptionStorage; + ReturnErrorOnFailure(sSessionResumptionStorage->Init(this->persistentStorageDelegate)); + this->sessionResumptionStorage = &sSessionResumptionStorage.get(); #else this->sessionResumptionStorage = nullptr; #endif @@ -292,12 +294,12 @@ struct CommonCaseDeviceServerInitParams : public ServerInitParams this->accessDelegate = Access::Examples::GetAccessControlDelegate(); // Inject ACL storage. (Don't initialize it.) - this->aclStorage = &sAclStorage; + this->aclStorage = &sAclStorage.get(); #if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS ChipLogProgress(AppServer, "Initializing subscription resumption storage..."); - ReturnErrorOnFailure(sSubscriptionResumptionStorage.Init(this->persistentStorageDelegate)); - this->subscriptionResumptionStorage = &sSubscriptionResumptionStorage; + ReturnErrorOnFailure(sSubscriptionResumptionStorage->Init(this->persistentStorageDelegate)); + this->subscriptionResumptionStorage = &sSubscriptionResumptionStorage.get(); #else ChipLogProgress(AppServer, "Subscription persistence not supported"); #endif @@ -305,7 +307,7 @@ struct CommonCaseDeviceServerInitParams : public ServerInitParams #if CHIP_CONFIG_ENABLE_ICD_CIP if (this->icdCheckInBackOffStrategy == nullptr) { - this->icdCheckInBackOffStrategy = &sDefaultICDCheckInBackOffStrategy; + this->icdCheckInBackOffStrategy = &sDefaultICDCheckInBackOffStrategy.get(); } #endif @@ -313,23 +315,23 @@ struct CommonCaseDeviceServerInitParams : public ServerInitParams } private: - static KvsPersistentStorageDelegate sKvsPersistenStorageDelegate; - static PersistentStorageOperationalKeystore sPersistentStorageOperationalKeystore; - static Credentials::PersistentStorageOpCertStore sPersistentStorageOpCertStore; - static Credentials::GroupDataProviderImpl sGroupDataProvider; - static chip::app::DefaultTimerDelegate sTimerDelegate; - static app::reporting::ReportSchedulerImpl sReportScheduler; + static Global sKvsPersistenStorageDelegate; + static Global sPersistentStorageOperationalKeystore; + static Global sPersistentStorageOpCertStore; + static Global sGroupDataProvider; + static Global sTimerDelegate; + static Global sReportScheduler; #if CHIP_CONFIG_ENABLE_SESSION_RESUMPTION - static SimpleSessionResumptionStorage sSessionResumptionStorage; + static Global sSessionResumptionStorage; #endif #if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS - static app::SimpleSubscriptionResumptionStorage sSubscriptionResumptionStorage; + static Global sSubscriptionResumptionStorage; #endif - static app::DefaultAclStorage sAclStorage; - static Crypto::DefaultSessionKeystore sSessionKeystore; + static Global sAclStorage; + static Global sSessionKeystore; #if CHIP_CONFIG_ENABLE_ICD_CIP - static app::DefaultICDCheckInBackOffStrategy sDefaultICDCheckInBackOffStrategy; + static Global sDefaultICDCheckInBackOffStrategy; #endif }; @@ -442,12 +444,13 @@ class Server return System::SystemClock().GetMonotonicMicroseconds64() - mInitTimestamp; } - static Server & GetInstance() { return sServer; } + static Server & GetInstance() { return sServer.get(); } private: Server() {} - static Server sServer; + friend class Global; + static Global sServer; void InitFailSafe(); void OnPlatformEvent(const DeviceLayer::ChipDeviceEvent & event); diff --git a/src/app/util/binding-table.cpp b/src/app/util/binding-table.cpp index 7ca3c4ba18aace..a6ca5ea12a31d0 100644 --- a/src/app/util/binding-table.cpp +++ b/src/app/util/binding-table.cpp @@ -24,7 +24,7 @@ namespace chip { -BindingTable BindingTable::sInstance; +Global BindingTable::sInstance; BindingTable::BindingTable() { diff --git a/src/app/util/binding-table.h b/src/app/util/binding-table.h index 4b8cc733410a9d..947e9e0e793e57 100644 --- a/src/app/util/binding-table.h +++ b/src/app/util/binding-table.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -82,10 +83,10 @@ class BindingTable CHIP_ERROR LoadFromStorage(); - static BindingTable & GetInstance() { return sInstance; } + static BindingTable & GetInstance() { return sInstance.get(); } private: - static BindingTable sInstance; + static Global sInstance; static constexpr uint32_t kStorageVersion = 1; static constexpr uint8_t kEntryStorageSize = TLV::EstimateStructOverhead( diff --git a/src/crypto/CHIPCryptoPALmbedTLS.cpp b/src/crypto/CHIPCryptoPALmbedTLS.cpp index 4df0ce97e30989..699811aa4c9efb 100644 --- a/src/crypto/CHIPCryptoPALmbedTLS.cpp +++ b/src/crypto/CHIPCryptoPALmbedTLS.cpp @@ -42,6 +42,7 @@ #include #include +#include #include #include #include @@ -63,7 +64,7 @@ typedef struct mbedtls_entropy_context mEntropy; } EntropyContext; -static EntropyContext gsEntropyContext; +static Global gsEntropyContext; static bool _isValidTagLength(size_t tag_length) { @@ -384,15 +385,16 @@ CHIP_ERROR PBKDF2_sha256::pbkdf2_sha256(const uint8_t * password, size_t plen, c static EntropyContext * get_entropy_context() { - if (!gsEntropyContext.mInitialized) + EntropyContext & entropyContext = gsEntropyContext.get(); + if (!entropyContext.mInitialized) { - mbedtls_entropy_init(&gsEntropyContext.mEntropy); - mbedtls_ctr_drbg_init(&gsEntropyContext.mDRBGCtxt); + mbedtls_entropy_init(&entropyContext.mEntropy); + mbedtls_ctr_drbg_init(&entropyContext.mDRBGCtxt); - gsEntropyContext.mInitialized = true; + entropyContext.mInitialized = true; } - return &gsEntropyContext; + return &entropyContext; } static mbedtls_ctr_drbg_context * get_drbg_context() diff --git a/src/include/platform/internal/GenericConnectivityManagerImpl_UDP.ipp b/src/include/platform/internal/GenericConnectivityManagerImpl_UDP.ipp index 86adff0bc096f3..828bcfc4f42c5c 100644 --- a/src/include/platform/internal/GenericConnectivityManagerImpl_UDP.ipp +++ b/src/include/platform/internal/GenericConnectivityManagerImpl_UDP.ipp @@ -24,6 +24,7 @@ #ifndef GENERIC_CONNECTIVITY_MANAGER_IMPL_UDP_CPP #define GENERIC_CONNECTIVITY_MANAGER_IMPL_UDP_CPP +#include #include namespace chip { @@ -33,8 +34,8 @@ namespace Internal { template chip::Inet::EndPointManager & GenericConnectivityManagerImpl_UDP::_UDPEndPointManager() { - static chip::Inet::UDPEndPointManagerImpl sUDPEndPointManagerImpl; - return sUDPEndPointManagerImpl; + static Global sUDPEndPointManagerImpl; + return sUDPEndPointManagerImpl.get(); } // Fully instantiate the generic implementation class in whatever compilation unit includes this file. diff --git a/src/lib/core/CHIPConfig.h b/src/lib/core/CHIPConfig.h index fca3472826a310..89fcdfed578bf2 100644 --- a/src/lib/core/CHIPConfig.h +++ b/src/lib/core/CHIPConfig.h @@ -187,6 +187,18 @@ #define CHIP_CONFIG_GLOBALS_NO_DESTRUCT 0 #endif // CHIP_CONFIG_GLOBALS_NO_DESTRUCT +/** + * @def CHIP_CONFIG_DYNAMICALLY_ALLOCATED_GLOBALS + * + * @brief + * Whether to use dynamic allocation for chip::Global objects. + * + * The default is to use static allocation. + */ +#ifndef CHIP_CONFIG_DYNAMICALLY_ALLOCATED_GLOBALS +#define CHIP_CONFIG_DYNAMICALLY_ALLOCATED_GLOBALS 0 +#endif // CHIP_CONFIG_DYNAMICALLY_ALLOCATED_GLOBALS + /** * @def CHIP_CONFIG_SHA256_CONTEXT_SIZE * diff --git a/src/lib/core/Global.h b/src/lib/core/Global.h index ddecf2bbeddb5b..c17590c24e58fd 100644 --- a/src/lib/core/Global.h +++ b/src/lib/core/Global.h @@ -97,17 +97,46 @@ class Global ~Global() = default; private: +#if CHIP_CONFIG_DYNAMICALLY_ALLOCATED_GLOBALS + std::remove_extent_t * mStorage = nullptr; + + T & _get() + { + mOnce.call(&create, this); + return *reinterpret_cast(mStorage); + } + + static void create(void * value) + { + auto self = static_cast *>(value); + self->mStorage = new T(); +#if !CHIP_CONFIG_GLOBALS_NO_DESTRUCT + CHIP_CXA_ATEXIT(&destroy, self->mStorage); +#endif // CHIP_CONFIG_GLOBALS_NO_DESTRUCT + } + + template , bool> = true> + static void destroy(void * value) + { + delete[] static_cast *>(value); + } + + template , bool> = true> + static void destroy(void * value) + { + delete static_cast(value); + } +#else // CHIP_CONFIG_DYNAMICALLY_ALLOCATED_GLOBALS // Zero-initialize everything. We should technically leave mStorage uninitialized, // but that can sometimes cause clang to be unable to constant-initialize the object. alignas(T) unsigned char mStorage[sizeof(T)] = {}; - OnceStrategy mOnce; T & _get() { - T * value = reinterpret_cast(mStorage); - mOnce.call(&create, value); - return *value; + mOnce.call(&create, mStorage); + return *reinterpret_cast(mStorage); } + static void create(void * value) { new (value) T(); @@ -115,7 +144,23 @@ class Global CHIP_CXA_ATEXIT(&destroy, value); #endif // CHIP_CONFIG_GLOBALS_NO_DESTRUCT } - static void destroy(void * value) { static_cast(value)->~T(); } + + template , bool> = true> + static void destroy(void * value) + { + using V = std::remove_extent_t; + for (std::size_t i = 0; i != std::extent_v; ++i) + (static_cast(value) + i)->~V(); + } + + template , bool> = true> + static void destroy(void * value) + { + static_cast(value)->~T(); + } +#endif // CHIP_CONFIG_DYNAMICALLY_ALLOCATED_GLOBALS + + OnceStrategy mOnce; #else // CHIP_CONFIG_GLOBALS_LAZY_INIT public: