+[[noreturn]] void singletonWarnLeakyDoubleRegistrationAndAbort(
+ const TypeDescriptor& type);
+
+[[noreturn]] void singletonWarnLeakyInstantiatingNotRegisteredAndAbort(
+ const TypeDescriptor& type);
+
+[[noreturn]] void singletonWarnRegisterMockEarlyAndAbort(
+ const TypeDescriptor& type);
+
+void singletonWarnDestroyInstanceLeak(
+ const TypeDescriptor& type,
+ const void* ptr);
+
+[[noreturn]] void singletonWarnCreateCircularDependencyAndAbort(
+ const TypeDescriptor& type);
+
+[[noreturn]] void singletonWarnCreateUnregisteredAndAbort(
+ const TypeDescriptor& type);
+
+[[noreturn]] void singletonWarnCreateBeforeRegistrationCompleteAndAbort(
+ const TypeDescriptor& type);
+
+void singletonPrintDestructionStackTrace(const TypeDescriptor& type);
+
+[[noreturn]] void singletonThrowNullCreator(const std::type_info& type);
+
+[[noreturn]] void singletonThrowGetInvokedAfterDestruction(
+ const TypeDescriptor& type);
+
+struct SingletonVaultState {
+ // The two stages of life for a vault, as mentioned in the class comment.
+ enum class Type {
+ Running,
+ Quiescing,
+ };
+
+ Type state{Type::Running};
+ bool registrationComplete{false};
+
+ // Each singleton in the vault can be in two states: dead
+ // (registered but never created), living (CreateFunc returned an instance).
+
+ void check(
+ Type expected,
+ const char* msg = "Unexpected singleton state change") const {
+ if (expected != state) {
+ throwUnexpectedState(msg);
+ }
+ }
+
+ [[noreturn]] static void throwUnexpectedState(const char* msg);
+};
+