+
+[[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;
+}
+
+void singletonPrintDestructionStackTrace(const TypeDescriptor& type) {
+ std::string output = "Singleton " + type.name() + " was released.\n";
+
+ auto stack_trace_getter = SingletonVault::stackTraceGetter().load();
+ auto stack_trace = stack_trace_getter ? stack_trace_getter() : "";
+ if (stack_trace.empty()) {
+ output += "Failed to get release stack trace.";
+ } else {
+ output += "Release stack trace:\n";
+ output += stack_trace;
+ }
+
+ LOG(ERROR) << output;
+}
+
+[[noreturn]] void singletonThrowNullCreator(const std::type_info& type) {
+ auto const msg = sformat(
+ "nullptr_t should be passed if you want {} to be default constructed",
+ demangle(type));
+ throw std::logic_error(msg);
+}
+
+[[noreturn]] void singletonThrowGetInvokedAfterDestruction(
+ const TypeDescriptor& type) {
+ throw std::runtime_error(
+ "Raw pointer to a singleton requested after its destruction."
+ " Singleton type is: " +
+ type.name());
+}
+
+[[noreturn]] void SingletonVaultState::throwUnexpectedState(const char* msg) {
+ throw std::logic_error(msg);
+}
+