From 85e70d8a078445ac368d42d412182dfc6266fcb2 Mon Sep 17 00:00:00 2001 From: Maxim Prokhorov Date: Wed, 11 Aug 2021 18:19:19 +0300 Subject: [PATCH] relay: workaround for gcc4.8 single-source build Resolve the code generation issue with vector methods being unable to store the exception info string in the same elf section (which apparently becomes duplicated, somehow, when building single .cpp) Error messages look like something like this: ``` vector.tcc:405 error: __c causes a section type conflict with __c _M_check_len(size_type(1), __EXCSTR("vector::_M_emplace_back_aux")); vector.tcc:71 note: '__c' was declared here __throw_length_error(__EXCSTR(__N("vector::reserve"))); ``` --- code/espurna/relay.cpp | 57 +++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/code/espurna/relay.cpp b/code/espurna/relay.cpp index a3ffb7b4..45f76891 100644 --- a/code/espurna/relay.cpp +++ b/code/espurna/relay.cpp @@ -209,25 +209,37 @@ String serialize(RelayMaskHelper mask) { // RELAY CONTROL // ----------------------------------------------------------------------------- -namespace { +// No-op provider, available for purely virtual relays that are controlled only via API -RelayProviderBase* _relayDummyProvider(); +struct DummyProvider : public RelayProviderBase { + const char* id() const override { + return "dummy"; + } -struct relay_t { + void change(bool) override { + } + + static RelayProviderBase* sharedInstance() { + static DummyProvider provider; + return &provider; + } +}; + +class Relay { public: // Struct defaults to empty relay configuration, as we allow switches to exist without real GPIOs - relay_t() = default; + Relay() = default; - relay_t(RelayProviderBasePtr&& provider_) : - provider(provider_.release()) + explicit Relay(RelayProviderBasePtr&& ptr) : + provider(ptr.release()) {} - relay_t(RelayProviderBase* provider_) : - provider(provider_) + explicit Relay(RelayProviderBase* ptr) : + provider(ptr) {} // ON / OFF actions implementation - RelayProviderBase* provider { _relayDummyProvider() }; + RelayProviderBase* provider { DummyProvider::sharedInstance() }; // Timers unsigned long delay_on { 0ul }; // Delay to turn relay ON @@ -253,7 +265,10 @@ public: bool group_report { false }; // Whether to report to group topic }; -std::vector _relays; +namespace { + +using Relays = std::vector; +Relays _relays; size_t _relayDummy { 0ul }; unsigned long _relay_flood_window { relay::build::floodWindowMs() }; @@ -322,26 +337,10 @@ void relayOnStatusChange(RelayStatusCallback callback) { _relay_status_change.push_front(callback); } -// No-op provider, available for purely virtual relays that are controlled only via API - -struct DummyProvider : public RelayProviderBase { - const char* id() const override { - return "dummy"; - } - - void change(bool) override { - } -}; +// Real GPIO provider, using BasePin interface to implement writers namespace { -RelayProviderBase* _relayDummyProvider() { - static DummyProvider provider; - return &provider; -} - -// Real GPIO provider, using BasePin interface to implement writers - struct GpioProvider : public RelayProviderBase { GpioProvider(size_t id, RelayType type, std::unique_ptr&& pin, std::unique_ptr&& reset_pin) : _id(id), @@ -575,14 +574,10 @@ private: #endif // RELAY_PROVIDER_STM_SUPPORT -} // namespace - // ----------------------------------------------------------------------------- // UTILITY // ----------------------------------------------------------------------------- -namespace { - bool _relayTryParseId(const char* p, size_t& id) { return tryParseId(p, relayCount, id); }