138 #include <condition_variable> 139 #include <functional> 147 #include <unordered_map> 148 #include <unordered_set> 151 #include <glog/logging.h> 154 #ifndef FOLLY_SINGLETON_TRY_GET 155 #define FOLLY_SINGLETON_TRY_GET 182 class SingletonVault;
198 if (
this != &other) {
263 bool registrationComplete{
false};
270 const char* msg =
"Unexpected singleton state change")
const {
271 if (expected !=
state) {
272 throw_exception<std::logic_error>(msg);
288 virtual bool hasLiveInstance() = 0;
289 virtual void createInstance() = 0;
290 virtual bool creationStarted() = 0;
292 virtual void destroyInstance() = 0;
301 template <
typename T>
307 template <
typename Tag,
typename VaultTag>
311 inline std::weak_ptr<T> get_weak();
312 inline std::shared_ptr<T> try_get();
314 inline void vivify();
316 void registerSingleton(CreateFunc
c, TeardownFunc
t);
317 void registerSingletonMock(CreateFunc
c, TeardownFunc
t);
318 bool hasLiveInstance()
override;
319 void createInstance()
override;
320 bool creationStarted()
override;
322 void destroyInstance()
override;
340 std::atomic<SingletonHolderState> state_{SingletonHolderState::NotRegistered};
343 std::atomic<std::thread::id> creating_thread_{};
361 T* instance_ptr_ =
nullptr;
362 CreateFunc create_ =
nullptr;
363 TeardownFunc teardown_ =
nullptr;
407 static Type defaultVaultType();
432 void registrationComplete();
464 void destroyInstances();
467 void reenableInstances();
471 return singletons_.rlock()->size();
478 bool eagerInitComplete()
const;
481 auto singletons = singletons_.rlock();
484 for (
const auto& p : *singletons) {
485 if (p.second->hasLiveInstance()) {
496 return singleton<>();
501 template <
typename VaultTag = detail::DefaultTag>
504 detail::createGlobal<SingletonVault, VaultTag>();
511 static auto stackTraceGetterPtr = detail::
513 return *stackTraceGetterPtr;
521 template <
typename T>
535 static void scheduleDestroyInstances();
537 typedef std::unordered_map<
548 std::unordered_set<detail::SingletonHolderBase*>,
579 [[deprecated(
"Replaced by try_get")]]
static T*
get() {
580 return getEntry().get();
587 [[deprecated(
"Replaced by try_get")]]
static std::weak_ptr<T>
get_weak() {
588 return getEntry().get_weak();
599 return getEntry().try_get();
603 return getEntry().try_get_fast();
612 std::nullptr_t =
nullptr,
623 auto vault = SingletonVault::singleton<VaultTag>();
625 vault->registerSingleton(&getEntry());
645 auto vault = SingletonVault::singleton<VaultTag>();
646 vault->addEagerInitSingleton(&getEntry());
661 std::nullptr_t =
nullptr,
663 make_mock([]() {
return new T; },
t);
673 auto& entry = getEntry();
675 entry.registerSingletonMock(c, getTeardownFunc(
t));
687 return [](
T*
v) {
delete v; };
694 template <
typename T,
typename Tag = detail::DefaultTag>
702 auto& entry = entryInstance();
703 if (entry.state != State::NotRegistered) {
706 entry.createFunc = createFunc;
707 entry.state = State::Dead;
715 make_mock([]() {
return new T; });
719 if (createFunc ==
nullptr) {
723 auto& entry = entryInstance();
726 entry.leakedPtrs.push_back(
std::exchange(entry.ptr,
nullptr));
728 entry.createFunc = createFunc;
729 entry.state = State::Dead;
733 enum class State { NotRegistered, Dead, Living };
740 std::atomic<State>
state{State::NotRegistered};
749 static auto entry = detail::createGlobal<Entry, Tag>();
754 auto& entry = entryInstance();
755 if (
UNLIKELY(entry.state != State::Living)) {
763 auto& entry = entryInstance();
765 std::lock_guard<std::mutex> lg(entry.mutex);
766 if (entry.state == State::Living) {
770 if (entry.state == State::NotRegistered) {
774 entry.ptr = entry.createFunc();
775 entry.state = State::Living;
SingletonHolderBase(TypeDescriptor typeDesc)
size_t livingSingletonCount() const
bool operator==(const TypeDescriptor &other) const
std::function< void(T *)> TeardownFunc
TypeDescriptor & operator=(const TypeDescriptor &other)
static detail::SingletonHolder< T >::TeardownFunc getTeardownFunc(TeardownFunc t)
std::unordered_map< detail::TypeDescriptor, detail::SingletonHolderBase *, detail::TypeDescriptorHasher > SingletonMap
void singletonThrowNullCreator(const std::type_info &type)
static SingletonVault * singleton()
static SingletonVault * singleton()
static Singleton< ShutdownSocketSet, PrivateTag > singleton
std::function< void(void *)> TeardownFunc
static void make_mock(std::nullptr_t=nullptr, typename Singleton< T >::TeardownFunc t=nullptr)
LeakySingleton(CreateFunc createFunc)
constexpr detail::Map< Move > move
static void make_mock(CreateFunc createFunc)
void singletonWarnCreateUnregisteredAndAbort(const TypeDescriptor &type)
SingletonVault(Type type=defaultVaultType())
void singletonWarnCreateCircularDependencyAndAbort(const TypeDescriptor &type)
void check(Type expected, const char *msg="Unexpected singleton state change") const
size_t operator()(const TypeDescriptor &ti) const
void singletonWarnLeakyInstantiatingNotRegisteredAndAbort(const TypeDescriptor &type)
std::function< T *(void)> CreateFunc
—— Concurrent Priority Queue Implementation ——
Synchronized< std::unordered_set< detail::SingletonHolderBase * >, SharedMutexSuppressTSAN > eagerInitSingletons_
folly::ReadMostlyMainPtr< T > instance_
static std::atomic< StackTraceGetterPtr > & stackTraceGetter()
static void make_mock(CreateFunc c, typename Singleton< T >::TeardownFunc t=nullptr)
void singletonThrowGetInvokedAfterDestruction(const TypeDescriptor &type)
Singleton(std::nullptr_t=nullptr, typename Singleton::TeardownFunc t=nullptr)
void singletonWarnRegisterMockEarlyAndAbort(const TypeDescriptor &type)
static Entry & entryInstance()
size_t hash_combine(const T &t, const Ts &...ts) noexcept(noexcept(hash_combine_generic(StdHasher{}, t, ts...)))
std::shared_ptr< folly::Baton<> > destroy_baton_
void singletonWarnDestroyInstanceLeak(const TypeDescriptor &type, const void *ptr)
static void createInstance()
static detail::SingletonHolder< T > & getEntry()
folly::ReadMostlyWeakPtr< T > instance_weak_fast_
TypeDescriptor(const TypeDescriptor &other)
size_t registeredSingletonCount() const
static void make_mock(std::nullptr_t=nullptr)
void singletonWarnLeakyDoubleRegistrationAndAbort(const TypeDescriptor &type)
ScopedExpunger(SingletonVault *v)
std::function< void *(void)> CreateFunc
static std::shared_ptr< T > try_get()
T exchange(T &obj, U &&new_value)
TypeDescriptor(const std::type_info &ti, const std::type_info &tag_ti)
std::weak_ptr< T > instance_weak_
void singletonWarnCreateBeforeRegistrationCompleteAndAbort(const TypeDescriptor &type)
TypeDescriptor type() const
void singletonPrintDestructionStackTrace(const TypeDescriptor &type)
std::shared_ptr< std::atomic< bool > > print_destructor_stack_trace_
static folly::ReadMostlySharedPtr< T > try_get_fast()
static std::weak_ptr< T > get_weak()
std::function< T *()> CreateFunc
std::function< T *(void)> CreateFunc
folly::ReadMostlySharedPtr< T > instance_copy_
Singleton(typename Singleton::CreateFunc c, typename Singleton::TeardownFunc t=nullptr)
std::function< void(T *)> TeardownFunc
Synchronized< std::vector< detail::TypeDescriptor >, SharedMutexSuppressTSAN > creationOrder_
std::list< T * > leakedPtrs
Singleton & shouldEagerInit()
Synchronized< detail::SingletonVaultState, SharedMutexReadPriority > state_
Synchronized< SingletonMap, SharedMutexSuppressTSAN > singletons_