Commit 4d897276 authored by Andrii Grynenko's avatar Andrii Grynenko Committed by Sara Golemon

Revert "Revert "Using type-tags for test SingletonVaults""

Summary:
This reverts commit 4893c09795ad4b1187518b184ac4812079039988.

Fix unit test in D1823663.

Test Plan: fbconfig -r folly fbmake dbg

Reviewed By: alikhtarov@fb.com

Subscribers: folly-diffs@, yfeldblum

FB internal diff: D1832645

Signature: t1:1832645:1423267466:6012f1d7700d540c7290c29b01b33148cf91183c
parent 5569e6fa
...@@ -86,11 +86,6 @@ void SingletonVault::reenableInstances() { ...@@ -86,11 +86,6 @@ void SingletonVault::reenableInstances() {
state_ = SingletonVaultState::Running; state_ = SingletonVaultState::Running;
} }
SingletonVault* SingletonVault::singleton() {
static SingletonVault* vault = new SingletonVault();
return vault;
}
void SingletonVault::scheduleDestroyInstances() { void SingletonVault::scheduleDestroyInstances() {
RequestContext::getStaticContext(); RequestContext::getStaticContext();
......
...@@ -399,7 +399,17 @@ class SingletonVault { ...@@ -399,7 +399,17 @@ class SingletonVault {
// A well-known vault; you can actually have others, but this is the // A well-known vault; you can actually have others, but this is the
// default. // default.
static SingletonVault* singleton(); static SingletonVault* singleton() {
return singleton<>();
}
// Gets singleton vault for any Tag. Non-default tag should be used in unit
// tests only.
template <typename VaultTag = detail::DefaultTag>
static SingletonVault* singleton() {
static SingletonVault* vault = new SingletonVault();
return vault;
}
private: private:
// The two stages of life for a vault, as mentioned in the class comment. // The two stages of life for a vault, as mentioned in the class comment.
...@@ -534,7 +544,9 @@ class SingletonVault { ...@@ -534,7 +544,9 @@ class SingletonVault {
// singletons. Create instances of this class in the global scope of // singletons. Create instances of this class in the global scope of
// type Singleton<T> to register your singleton for later access via // type Singleton<T> to register your singleton for later access via
// Singleton<T>::get(). // Singleton<T>::get().
template <typename T, typename Tag = detail::DefaultTag> template <typename T,
typename Tag = detail::DefaultTag,
typename VaultTag = detail::DefaultTag /* for testing */>
class Singleton { class Singleton {
public: public:
typedef std::function<T*(void)> CreateFunc; typedef std::function<T*(void)> CreateFunc;
...@@ -543,9 +555,9 @@ class Singleton { ...@@ -543,9 +555,9 @@ class Singleton {
// Generally your program life cycle should be fine with calling // Generally your program life cycle should be fine with calling
// get() repeatedly rather than saving the reference, and then not // get() repeatedly rather than saving the reference, and then not
// call get() during process shutdown. // call get() during process shutdown.
static T* get(SingletonVault* vault = nullptr /* for testing */) { static T* get() {
return static_cast<T*>( return static_cast<T*>(
(vault ?: SingletonVault::singleton())->get_ptr(typeDescriptor())); SingletonVault::singleton<VaultTag>()->get_ptr(typeDescriptor()));
} }
// Same as get, but should be preffered to it in the same compilation // Same as get, but should be preffered to it in the same compilation
...@@ -554,7 +566,7 @@ class Singleton { ...@@ -554,7 +566,7 @@ class Singleton {
if (LIKELY(entry_->state == detail::SingletonEntryState::Living)) { if (LIKELY(entry_->state == detail::SingletonEntryState::Living)) {
return reinterpret_cast<T*>(entry_->instance_ptr); return reinterpret_cast<T*>(entry_->instance_ptr);
} else { } else {
return get(vault_); return get();
} }
} }
...@@ -562,10 +574,9 @@ class Singleton { ...@@ -562,10 +574,9 @@ class Singleton {
// singleton, you can try to do so with a weak_ptr. Avoid this when // singleton, you can try to do so with a weak_ptr. Avoid this when
// possible but the inability to lock the weak pointer can be a // possible but the inability to lock the weak pointer can be a
// signal that the vault has been destroyed. // signal that the vault has been destroyed.
static std::weak_ptr<T> get_weak( static std::weak_ptr<T> get_weak() {
SingletonVault* vault = nullptr /* for testing */) {
auto weak_void_ptr = auto weak_void_ptr =
(vault ?: SingletonVault::singleton())->get_weak(typeDescriptor()); (SingletonVault::singleton<VaultTag>())->get_weak(typeDescriptor());
// This is ugly and inefficient, but there's no other way to do it, because // This is ugly and inefficient, but there's no other way to do it, because
// there's no static_pointer_cast for weak_ptr. // there's no static_pointer_cast for weak_ptr.
...@@ -588,7 +599,7 @@ class Singleton { ...@@ -588,7 +599,7 @@ class Singleton {
} }
return std::static_pointer_cast<T>(shared_void_ptr); return std::static_pointer_cast<T>(shared_void_ptr);
} else { } else {
return get_weak(vault_); return get_weak();
} }
} }
...@@ -599,26 +610,19 @@ class Singleton { ...@@ -599,26 +610,19 @@ class Singleton {
T* operator->() { return ptr(); } T* operator->() { return ptr(); }
explicit Singleton(std::nullptr_t _ = nullptr, explicit Singleton(std::nullptr_t _ = nullptr,
Singleton::TeardownFunc t = nullptr, Singleton::TeardownFunc t = nullptr) :
SingletonVault* vault = nullptr) : Singleton ([]() { return new T; }, std::move(t)) {
Singleton ([]() { return new T; },
std::move(t),
vault) {
} }
explicit Singleton(Singleton::CreateFunc c, explicit Singleton(Singleton::CreateFunc c,
Singleton::TeardownFunc t = nullptr, Singleton::TeardownFunc t = nullptr) {
SingletonVault* vault = nullptr) {
if (c == nullptr) { if (c == nullptr) {
throw std::logic_error( throw std::logic_error(
"nullptr_t should be passed if you want T to be default constructed"); "nullptr_t should be passed if you want T to be default constructed");
} }
if (vault == nullptr) { auto vault = SingletonVault::singleton<VaultTag>();
vault = SingletonVault::singleton();
}
vault_ = vault;
entry_ = entry_ =
&(vault->registerSingleton(typeDescriptor(), c, getTeardownFunc(t))); &(vault->registerSingleton(typeDescriptor(), c, getTeardownFunc(t)));
} }
...@@ -634,22 +638,18 @@ class Singleton { ...@@ -634,22 +638,18 @@ class Singleton {
* regular singletons. * regular singletons.
*/ */
static void make_mock(std::nullptr_t c = nullptr, static void make_mock(std::nullptr_t c = nullptr,
typename Singleton<T>::TeardownFunc t = nullptr, typename Singleton<T>::TeardownFunc t = nullptr) {
SingletonVault* vault = nullptr /* for testing */ ) { make_mock([]() { return new T; }, t);
make_mock([]() { return new T; }, t, vault);
} }
static void make_mock(CreateFunc c, static void make_mock(CreateFunc c,
typename Singleton<T>::TeardownFunc t = nullptr, typename Singleton<T>::TeardownFunc t = nullptr) {
SingletonVault* vault = nullptr /* for testing */ ) {
if (c == nullptr) { if (c == nullptr) {
throw std::logic_error( throw std::logic_error(
"nullptr_t should be passed if you want T to be default constructed"); "nullptr_t should be passed if you want T to be default constructed");
} }
if (vault == nullptr) { auto vault = SingletonVault::singleton<VaultTag>();
vault = SingletonVault::singleton();
}
vault->registerMockSingleton( vault->registerMockSingleton(
typeDescriptor(), typeDescriptor(),
...@@ -680,7 +680,6 @@ class Singleton { ...@@ -680,7 +680,6 @@ class Singleton {
// We rely on the fact that Singleton destructor won't reset this pointer, so // We rely on the fact that Singleton destructor won't reset this pointer, so
// it can be "safely" used even after static Singleton object is destroyed. // it can be "safely" used even after static Singleton object is destroyed.
detail::SingletonEntry* entry_; detail::SingletonEntry* entry_;
SingletonVault* vault_;
}; };
} }
This diff is collapsed.
...@@ -40,12 +40,16 @@ TEST(SingletonVault, singletonReturnsSingletonInstance) { ...@@ -40,12 +40,16 @@ TEST(SingletonVault, singletonReturnsSingletonInstance) {
EXPECT_EQ(c, cpp); EXPECT_EQ(c, cpp);
} }
struct TestTag {};
template <typename T, typename Tag = folly::detail::DefaultTag>
using SingletonTest = folly::Singleton <T, Tag, TestTag>;
TEST(SingletonVault, singletonsAreCreatedAndDestroyed) { TEST(SingletonVault, singletonsAreCreatedAndDestroyed) {
auto *vault = new folly::SingletonVault(); auto vault = folly::SingletonVault::singleton<TestTag>();
folly::Singleton<InstanceCounter> counter_singleton(nullptr, nullptr, vault); SingletonTest<InstanceCounter> counter_singleton;
SingletonVault_registrationComplete((SingletonVault_t*) vault); SingletonVault_registrationComplete((SingletonVault_t*) vault);
InstanceCounter *counter = folly::Singleton<InstanceCounter>::get(vault); InstanceCounter *counter = SingletonTest<InstanceCounter>::get();
EXPECT_EQ(instance_counter_instances, 1); EXPECT_EQ(instance_counter_instances, 1);
delete vault; SingletonVault_destroyInstances((SingletonVault_t*) vault);
EXPECT_EQ(instance_counter_instances, 0); EXPECT_EQ(instance_counter_instances, 0);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment