Skip to content

Commit

Permalink
Resolve and save the type info of lambda creator
Browse files Browse the repository at this point in the history
Differential Revision: D67317752

fbshipit-source-id: 6ac613fa7d291e2666c1a602ac55ca8c33071707
  • Loading branch information
Tao Chen (RPC) authored and facebook-github-bot committed Jan 9, 2025
1 parent 30d997e commit c77faa0
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 29 deletions.
67 changes: 45 additions & 22 deletions third-party/folly/src/folly/observer/Observer-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,59 @@

namespace folly {
namespace observer_detail {
template <typename F>
observer::Observer<ResultOfUnwrapSharedPtr<F>> makeObserver(
F&& creator,
std::optional<Core::CreatorContext> creatorContext = std::nullopt) {
if (!creatorContext) {
creatorContext = Core::CreatorContext{&typeid(F)};
}
auto core = Core::create(
[creator_2 = std::forward<F>(creator)]() mutable {
return std::static_pointer_cast<const void>(creator_2());
},
std::move(creatorContext).value());

ObserverManager::initCore(core);

return observer::Observer<ResultOfUnwrapSharedPtr<F>>(core);
}

template <typename F>
observer::Observer<ResultOfNoObserverUnwrap<F>> makeObserver(F&& creator) {
return observer::makeObserver(
return makeObserver(
[creator_2 = std::forward<F>(creator)]() mutable {
return std::make_shared<ResultOfNoObserverUnwrap<F>>(creator_2());
});
},
Core::CreatorContext{&typeid(F)});
}

template <typename F>
observer::Observer<ResultOfUnwrapSharedPtr<F>> makeValueObserver(
F&& creator,
std::optional<Core::CreatorContext> creatorContext = std::nullopt) {
if (!creatorContext) {
creatorContext = Core::CreatorContext{&typeid(F)};
}
return makeObserver(
[activeValue = std::shared_ptr<const ResultOfUnwrapSharedPtr<F>>(),
creator_2 = std::forward<F>(creator)]() mutable {
auto newValue = creator_2();
if (!activeValue || !(*activeValue == *newValue)) {
activeValue = newValue;
}
return activeValue;
},
std::move(creatorContext));
}

template <typename F>
observer::Observer<ResultOfNoObserverUnwrap<F>> makeValueObserver(F&& creator) {
return observer::makeValueObserver(
return makeValueObserver(
[creator_2 = std::forward<F>(creator)]() mutable {
return std::make_shared<ResultOfNoObserverUnwrap<F>>(creator_2());
});
},
Core::CreatorContext{&typeid(F)});
}
} // namespace observer_detail

Expand Down Expand Up @@ -80,14 +119,7 @@ Observer<T> unwrapValue(Observer<Observer<T>> oo) {
template <typename F>
Observer<observer_detail::ResultOfUnwrapSharedPtr<F>> makeObserver(
F&& creator) {
auto core = observer_detail::Core::create(
[creator_2 = std::forward<F>(creator)]() mutable {
return std::static_pointer_cast<const void>(creator_2());
});

observer_detail::ObserverManager::initCore(core);

return Observer<observer_detail::ResultOfUnwrapSharedPtr<F>>(core);
return observer_detail::makeObserver(std::forward<F>(creator));
}

template <typename F>
Expand Down Expand Up @@ -277,16 +309,7 @@ Observer<observer_detail::ResultOfUnwrapObserver<F>> makeValueObserver(
template <typename F>
Observer<observer_detail::ResultOfUnwrapSharedPtr<F>> makeValueObserver(
F&& creator) {
return makeObserver(
[activeValue =
std::shared_ptr<const observer_detail::ResultOfUnwrapSharedPtr<F>>(),
creator_2 = std::forward<F>(creator)]() mutable {
auto newValue = creator_2();
if (!activeValue || !(*activeValue == *newValue)) {
activeValue = newValue;
}
return activeValue;
});
return observer_detail::makeValueObserver(std::forward<F>(creator));
}

} // namespace observer
Expand Down
4 changes: 4 additions & 0 deletions third-party/folly/src/folly/observer/Observer.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,10 @@ class Observer {
[[nodiscard]] CallbackHandle addCallback(
Function<void(Snapshot<T>)> callback) const;

const std::type_info* getCreatorTypeInfo() const {
return core_->getCreatorContext().typeInfo;
}

private:
template <typename Observable, typename Traits>
friend class ObserverCreator;
Expand Down
14 changes: 10 additions & 4 deletions third-party/folly/src/folly/observer/detail/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,11 @@ void Core::setForceRefresh() {
forceRefresh_ = true;
}

Core::Core(folly::Function<std::shared_ptr<const void>()> creator)
: creator_(std::move(creator)) {}
Core::Core(
folly::Function<std::shared_ptr<const void>()> creator,
CreatorContext creatorContext)
: creator_(std::move(creator)),
creatorContext_(std::move(creatorContext)) {}

Core::~Core() {
dependencies_.withWLock([](const Dependencies& dependencies) {
Expand All @@ -158,8 +161,11 @@ Core::~Core() {
});
}

Core::Ptr Core::create(folly::Function<std::shared_ptr<const void>()> creator) {
auto core = Core::Ptr(new Core(std::move(creator)));
Core::Ptr Core::create(
folly::Function<std::shared_ptr<const void>()> creator,
CreatorContext creatorContext) {
auto core =
Core::Ptr(new Core(std::move(creator), std::move(creatorContext)));
return core;
}

Expand Down
15 changes: 13 additions & 2 deletions third-party/folly/src/folly/observer/detail/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,15 @@ class Core : public std::enable_shared_from_this<Core> {
using Ptr = std::shared_ptr<Core>;
using WeakPtr = std::weak_ptr<Core>;

struct CreatorContext {
const std::type_info* typeInfo;
};
/**
* Blocks until creator is successfully run by ObserverManager
*/
static Ptr create(folly::Function<std::shared_ptr<const void>()> creator);
static Ptr create(
folly::Function<std::shared_ptr<const void>()> creator,
CreatorContext creatorContext);

/**
* View of the observed object and its version
Expand Down Expand Up @@ -90,10 +95,14 @@ class Core : public std::enable_shared_from_this<Core> {
*/
void setForceRefresh();

const CreatorContext& getCreatorContext() const { return creatorContext_; }

~Core();

private:
explicit Core(folly::Function<std::shared_ptr<const void>()> creator);
Core(
folly::Function<std::shared_ptr<const void>()> creator,
CreatorContext creatorContext);

void addDependent(Core::WeakPtr dependent);
void maybeRemoveStaleDependents();
Expand All @@ -114,6 +123,8 @@ class Core : public std::enable_shared_from_this<Core> {

folly::Function<std::shared_ptr<const void>()> creator_;

CreatorContext creatorContext_;

mutable SharedMutex refreshMutex_;

bool forceRefresh_{false};
Expand Down
88 changes: 87 additions & 1 deletion third-party/folly/src/folly/observer/test/ObserverTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <thread>

#include <utility>
#include <folly/Demangle.h>
#include <folly/Singleton.h>
#include <folly/fibers/FiberManager.h>
#include <folly/fibers/FiberManagerMap.h>
Expand All @@ -29,11 +30,12 @@
#include <folly/observer/ReadMostlyTLObserver.h>
#include <folly/observer/SimpleObservable.h>
#include <folly/observer/WithJitter.h>
#include <folly/portability/GMock.h>
#include <folly/portability/GTest.h>
#include <folly/synchronization/Baton.h>

using namespace std::literals;
using namespace folly::observer;
using ::testing::StartsWith;

namespace {

Expand All @@ -42,6 +44,9 @@ struct AltAtomic : std::atomic<T> {};

} // namespace

namespace folly {
namespace observer {

TEST(Observer, Observable) {
SimpleObservable<int> observable(42);
auto observer = observable.getObserver();
Expand Down Expand Up @@ -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<int>(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<int>(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<int> observable{42};
auto observer = observable.getObserver();
EXPECT_EQ(42, **observer);
EXPECT_THAT(
folly::demangle(*observer.getCreatorTypeInfo()).toStdString(),
StartsWith(prefix));
}

} // namespace observer
} // namespace folly

0 comments on commit c77faa0

Please sign in to comment.