diff --git a/folly/settings/detail/SettingsImpl.h b/folly/settings/detail/SettingsImpl.h index 3f1d0b9007a..fa2f942ee6d 100644 --- a/folly/settings/detail/SettingsImpl.h +++ b/folly/settings/detail/SettingsImpl.h @@ -74,6 +74,7 @@ class SettingCoreBase { virtual void forceResetToDefault(SnapshotBase* snapshot) = 0; virtual const SettingMetadata& meta() const = 0; virtual uint64_t accessCount() const = 0; + virtual bool hasHadCallbacks() const = 0; virtual ~SettingCoreBase() {} /** @@ -192,6 +193,7 @@ class SnapshotBase { std::pair valueAndReason() const; const std::string& fullName() const { return fullName_; } uint64_t accessCount() const { return core_.accessCount(); } + bool hasHadCallbacks() const { return core_.hasHadCallbacks(); } private: const std::string& fullName_; @@ -335,6 +337,8 @@ class SettingCore : public SettingCoreBase { uint64_t accessCount() const override { return AccessCounter::count(); } + bool hasHadCallbacks() const override { return hasHadCallbacks_.load(); } + /** * @param trivialStorage must refer to the same location * as the internal trivialStorage_. This hint will @@ -387,6 +391,7 @@ class SettingCore : public SettingCoreBase { SettingCore& setting_; }; CallbackHandle addCallback(UpdateCallback callback) { + hasHadCallbacks_.store(true); auto callbackPtr = copy_to_shared_ptr(std::move(callback)); auto copiedPtr = callbackPtr; @@ -420,6 +425,7 @@ class SettingCore : public SettingCoreBase { std::atomic& trivialStorage_; F14FastSet> callbacks_; + std::atomic hasHadCallbacks_{false}; /* Thread local versions start at 0, this will force a read on first access. */ diff --git a/folly/settings/test/SettingsTest.cpp b/folly/settings/test/SettingsTest.cpp index 3ea06e4e585..06dd1d284b4 100644 --- a/folly/settings/test/SettingsTest.cpp +++ b/folly/settings/test/SettingsTest.cpp @@ -645,6 +645,11 @@ TEST(SettingsTest, callback) { some_ns::FOLLY_SETTING(follytest, some_flag).set("e"); EXPECT_EQ(callbackInvocations, 4); EXPECT_EQ(lastCallbackValue, "d"); + + folly::settings::Snapshot snapshot; + snapshot.forEachSetting([](const auto& s) { + EXPECT_EQ(s.hasHadCallbacks(), s.fullName() == "follytest_some_flag"); + }); } TEST(SettingsTest, observers) { @@ -661,6 +666,11 @@ TEST(SettingsTest, observers) { folly::observer_detail::ObserverManager::waitForAllUpdates(); EXPECT_EQ(**observer, "new value"); EXPECT_EQ(updatedFromCallback, "new value"); + + folly::settings::Snapshot snapshot; + snapshot.forEachSetting([](const auto& s) { + EXPECT_EQ(s.hasHadCallbacks(), s.fullName() == "follytest_some_flag"); + }); } TEST(Settings, immutables) {