diff --git a/third-party/folly/src/folly/observer/Observer-inl.h b/third-party/folly/src/folly/observer/Observer-inl.h index cc059de0bdba6a..b3b38443e7a96b 100644 --- a/third-party/folly/src/folly/observer/Observer-inl.h +++ b/third-party/folly/src/folly/observer/Observer-inl.h @@ -21,20 +21,59 @@ namespace folly { namespace observer_detail { +template +observer::Observer> makeObserver( + F&& creator, + std::optional creatorContext = std::nullopt) { + if (!creatorContext) { + creatorContext = Core::CreatorContext{&typeid(F)}; + } + auto core = Core::create( + [creator_2 = std::forward(creator)]() mutable { + return std::static_pointer_cast(creator_2()); + }, + std::move(creatorContext).value()); + + ObserverManager::initCore(core); + + return observer::Observer>(core); +} + template observer::Observer> makeObserver(F&& creator) { - return observer::makeObserver( + return makeObserver( [creator_2 = std::forward(creator)]() mutable { return std::make_shared>(creator_2()); - }); + }, + Core::CreatorContext{&typeid(F)}); +} + +template +observer::Observer> makeValueObserver( + F&& creator, + std::optional creatorContext = std::nullopt) { + if (!creatorContext) { + creatorContext = Core::CreatorContext{&typeid(F)}; + } + return makeObserver( + [activeValue = std::shared_ptr>(), + creator_2 = std::forward(creator)]() mutable { + auto newValue = creator_2(); + if (!activeValue || !(*activeValue == *newValue)) { + activeValue = newValue; + } + return activeValue; + }, + std::move(creatorContext)); } template observer::Observer> makeValueObserver(F&& creator) { - return observer::makeValueObserver( + return makeValueObserver( [creator_2 = std::forward(creator)]() mutable { return std::make_shared>(creator_2()); - }); + }, + Core::CreatorContext{&typeid(F)}); } } // namespace observer_detail @@ -80,14 +119,7 @@ Observer unwrapValue(Observer> oo) { template Observer> makeObserver( F&& creator) { - auto core = observer_detail::Core::create( - [creator_2 = std::forward(creator)]() mutable { - return std::static_pointer_cast(creator_2()); - }); - - observer_detail::ObserverManager::initCore(core); - - return Observer>(core); + return observer_detail::makeObserver(std::forward(creator)); } template @@ -277,16 +309,7 @@ Observer> makeValueObserver( template Observer> makeValueObserver( F&& creator) { - return makeObserver( - [activeValue = - std::shared_ptr>(), - creator_2 = std::forward(creator)]() mutable { - auto newValue = creator_2(); - if (!activeValue || !(*activeValue == *newValue)) { - activeValue = newValue; - } - return activeValue; - }); + return observer_detail::makeValueObserver(std::forward(creator)); } } // namespace observer diff --git a/third-party/folly/src/folly/observer/Observer.h b/third-party/folly/src/folly/observer/Observer.h index fc2fc719c5788a..9efa13f4f226f8 100644 --- a/third-party/folly/src/folly/observer/Observer.h +++ b/third-party/folly/src/folly/observer/Observer.h @@ -246,6 +246,10 @@ class Observer { [[nodiscard]] CallbackHandle addCallback( Function)> callback) const; + const std::type_info* getCreatorTypeInfo() const { + return core_->getCreatorContext().typeInfo; + } + private: template friend class ObserverCreator; diff --git a/third-party/folly/src/folly/observer/detail/Core.cpp b/third-party/folly/src/folly/observer/detail/Core.cpp index 569669dff8c7f8..99275ca71674d5 100644 --- a/third-party/folly/src/folly/observer/detail/Core.cpp +++ b/third-party/folly/src/folly/observer/detail/Core.cpp @@ -147,8 +147,11 @@ void Core::setForceRefresh() { forceRefresh_ = true; } -Core::Core(folly::Function()> creator) - : creator_(std::move(creator)) {} +Core::Core( + folly::Function()> creator, + CreatorContext creatorContext) + : creator_(std::move(creator)), + creatorContext_(std::move(creatorContext)) {} Core::~Core() { dependencies_.withWLock([](const Dependencies& dependencies) { @@ -158,8 +161,11 @@ Core::~Core() { }); } -Core::Ptr Core::create(folly::Function()> creator) { - auto core = Core::Ptr(new Core(std::move(creator))); +Core::Ptr Core::create( + folly::Function()> creator, + CreatorContext creatorContext) { + auto core = + Core::Ptr(new Core(std::move(creator), std::move(creatorContext))); return core; } diff --git a/third-party/folly/src/folly/observer/detail/Core.h b/third-party/folly/src/folly/observer/detail/Core.h index 3ea64af66fbbaa..c078f6ae3b1378 100644 --- a/third-party/folly/src/folly/observer/detail/Core.h +++ b/third-party/folly/src/folly/observer/detail/Core.h @@ -41,10 +41,15 @@ class Core : public std::enable_shared_from_this { using Ptr = std::shared_ptr; using WeakPtr = std::weak_ptr; + struct CreatorContext { + const std::type_info* typeInfo; + }; /** * Blocks until creator is successfully run by ObserverManager */ - static Ptr create(folly::Function()> creator); + static Ptr create( + folly::Function()> creator, + CreatorContext creatorContext); /** * View of the observed object and its version @@ -90,10 +95,14 @@ class Core : public std::enable_shared_from_this { */ void setForceRefresh(); + const CreatorContext& getCreatorContext() const { return creatorContext_; } + ~Core(); private: - explicit Core(folly::Function()> creator); + Core( + folly::Function()> creator, + CreatorContext creatorContext); void addDependent(Core::WeakPtr dependent); void maybeRemoveStaleDependents(); @@ -114,6 +123,8 @@ class Core : public std::enable_shared_from_this { folly::Function()> creator_; + CreatorContext creatorContext_; + mutable SharedMutex refreshMutex_; bool forceRefresh_{false}; diff --git a/third-party/folly/src/folly/observer/test/ObserverTest.cpp b/third-party/folly/src/folly/observer/test/ObserverTest.cpp index 881a54f87b981f..aace87638eede7 100644 --- a/third-party/folly/src/folly/observer/test/ObserverTest.cpp +++ b/third-party/folly/src/folly/observer/test/ObserverTest.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -29,11 +30,12 @@ #include #include #include +#include #include #include using namespace std::literals; -using namespace folly::observer; +using ::testing::StartsWith; namespace { @@ -42,6 +44,9 @@ struct AltAtomic : std::atomic {}; } // namespace +namespace folly { +namespace observer { + TEST(Observer, Observable) { SimpleObservable observable(42); auto observer = observable.getObserver(); @@ -1209,3 +1214,84 @@ TEST(Observer, ReenableSingletonWithPendingUpdate) { std::this_thread::sleep_for(std::chrono::milliseconds{100}); EXPECT_EQ(42, **observer); } + +TEST(Observer, TestMakeObserverWithTypeInfo) { + const std::string prefix = + "folly::observer::Observer_TestMakeObserverWithTypeInfo_Test"; + { + auto observer = folly::observer::makeObserver([] { return 42; }); + EXPECT_EQ(42, **observer); + EXPECT_THAT( + folly::demangle(*observer.getCreatorTypeInfo()).toStdString(), + StartsWith(prefix)); + } + { + auto observer = folly::observer::makeObserver([] { + return std::make_shared(42); + }); + EXPECT_EQ(42, **observer); + EXPECT_THAT( + folly::demangle(*observer.getCreatorTypeInfo()).toStdString(), + StartsWith(prefix)); + } + { + auto observer1 = folly::observer::makeObserver([] { return 1; }); + auto observer = folly::observer::makeObserver([observer1] { + return observer1; + }); + EXPECT_EQ(1, **observer); + EXPECT_THAT( + folly::demangle(*observer1.getCreatorTypeInfo()).toStdString(), + StartsWith(prefix)); + EXPECT_THAT( + folly::demangle(*observer.getCreatorTypeInfo()).toStdString(), + StartsWith("folly::observer::unwrap")); + } +} + +TEST(Observer, TestMakeValueObserverWithTypeInfo) { + const std::string prefix = + "folly::observer::Observer_TestMakeValueObserverWithTypeInfo_Test"; + { + auto observer = folly::observer::makeValueObserver([] { return 42; }); + EXPECT_EQ(42, **observer); + EXPECT_THAT( + folly::demangle(*observer.getCreatorTypeInfo()).toStdString(), + StartsWith(prefix)); + } + { + auto observer = folly::observer::makeValueObserver([] { + return std::make_shared(42); + }); + EXPECT_EQ(42, **observer); + EXPECT_THAT( + folly::demangle(*observer.getCreatorTypeInfo()).toStdString(), + StartsWith(prefix)); + } + { + auto observer1 = folly::observer::makeValueObserver([] { return 1; }); + auto observer = folly::observer::makeValueObserver([observer1] { + return observer1; + }); + EXPECT_EQ(1, **observer); + EXPECT_THAT( + folly::demangle(*observer1.getCreatorTypeInfo()).toStdString(), + StartsWith(prefix)); + EXPECT_THAT( + folly::demangle(*observer.getCreatorTypeInfo()).toStdString(), + StartsWith("folly::observer::unwrap")); + } +} + +TEST(Observer, TestSimpleObservableWithTypeInfo) { + const std::string prefix = "folly::observer::ObserverCreator"; + folly::observer::SimpleObservable observable{42}; + auto observer = observable.getObserver(); + EXPECT_EQ(42, **observer); + EXPECT_THAT( + folly::demangle(*observer.getCreatorTypeInfo()).toStdString(), + StartsWith(prefix)); +} + +} // namespace observer +} // namespace folly