+[[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);
+}
+
+} // namespace detail
+