+std::string TypeDescriptor::name() const {
+ auto ret = demangle(ti_.name());
+ if (tag_ti_ != std::type_index(typeid(DefaultTag))) {
+ ret += "/";
+ ret += demangle(tag_ti_.name());
+ }
+ return ret.toStdString();
+}
+
+[[noreturn]] void singletonWarnDoubleRegistrationAndAbort(
+ const TypeDescriptor& type) {
+ // Ensure the availability of std::cerr
+ std::ios_base::Init ioInit;
+ std::cerr << "Double registration of singletons of the same "
+ "underlying type; check for multiple definitions "
+ "of type folly::Singleton<"
+ << type.name() << ">\n";
+ std::abort();
+}
+
+[[noreturn]] void singletonWarnLeakyDoubleRegistrationAndAbort(
+ const TypeDescriptor& type) {
+ // Ensure the availability of std::cerr
+ std::ios_base::Init ioInit;
+ std::cerr << "Double registration of singletons of the same "
+ "underlying type; check for multiple definitions "
+ "of type folly::LeakySingleton<"
+ << type.name() << ">\n";
+ std::abort();
+}
+
+[[noreturn]] void singletonWarnLeakyInstantiatingNotRegisteredAndAbort(
+ const TypeDescriptor& type) {
+ auto ptr = SingletonVault::stackTraceGetter().load();
+ LOG(FATAL) << "Creating instance for unregistered singleton: "
+ << type.name() << "\n"
+ << "Stacktrace:"
+ << "\n" << (ptr ? (*ptr)() : "(not available)");
+}
+
+[[noreturn]] void singletonWarnRegisterMockEarlyAndAbort(
+ const TypeDescriptor& type) {
+ LOG(FATAL) << "Registering mock before singleton was registered: "
+ << type.name();
+}
+
+void singletonWarnDestroyInstanceLeak(
+ const TypeDescriptor& type,
+ const void* ptr) {
+ LOG(ERROR) << "Singleton of type " << type.name() << " has a "
+ << "living reference at destroyInstances time; beware! Raw "
+ << "pointer is " << ptr << ". It is very likely "
+ << "that some other singleton is holding a shared_ptr to it. "
+ << "This singleton will be leaked (even if a shared_ptr to it "
+ << "is eventually released)."
+ << "Make sure dependencies between these singletons are "
+ << "properly defined.";
+}
+
+[[noreturn]] void singletonWarnCreateCircularDependencyAndAbort(
+ const TypeDescriptor& type) {
+ LOG(FATAL) << "circular singleton dependency: " << type.name();
+}
+
+[[noreturn]] void singletonWarnCreateUnregisteredAndAbort(
+ const TypeDescriptor& type) {
+ auto ptr = SingletonVault::stackTraceGetter().load();
+ LOG(FATAL) << "Creating instance for unregistered singleton: "
+ << type.name() << "\n"
+ << "Stacktrace:"
+ << "\n"
+ << (ptr ? (*ptr)() : "(not available)");
+}
+
+[[noreturn]] void singletonWarnCreateBeforeRegistrationCompleteAndAbort(
+ const TypeDescriptor& type) {
+ auto stack_trace_getter = SingletonVault::stackTraceGetter().load();
+ auto stack_trace = stack_trace_getter ? stack_trace_getter() : "";
+ if (!stack_trace.empty()) {
+ stack_trace = "Stack trace:\n" + stack_trace;
+ }
+
+ LOG(FATAL) << "Singleton " << type.name() << " requested before "
+ << "registrationComplete() call.\n"
+ << "This usually means that either main() never called "
+ << "folly::init, or singleton was requested before main() "
+ << "(which is not allowed).\n"
+ << stack_trace;
+}