std::lock_guard<std::mutex> entry_lock(mutex_);
if (state_ != SingletonHolderState::NotRegistered) {
- throw std::logic_error("Double registration");
+ LOG(FATAL) << "Double registration of singleton: " << type_.name();
}
create_ = std::move(c);
template <typename T>
void SingletonHolder<T>::registerSingletonMock(CreateFunc c, TeardownFunc t) {
if (state_ == SingletonHolderState::NotRegistered) {
- throw std::logic_error("Registering mock before singleton was registered");
+ LOG(FATAL)
+ << "Registering mock before singleton was registered: " << type_.name();
}
destroyInstance();
// for creating_thread if it was set by other thread, but we only care about
// it if it was set by current thread anyways.
if (creating_thread_ == std::this_thread::get_id()) {
- throw std::out_of_range(std::string("circular singleton dependency: ") +
- type_.name());
+ LOG(FATAL) << "circular singleton dependency: " << type_.name();
}
std::lock_guard<std::mutex> entry_lock(mutex_);
return;
}
if (state_ == SingletonHolderState::NotRegistered) {
- throw std::out_of_range("Creating instance for unregistered singleton");
+ auto ptr = SingletonVault::stackTraceGetter().load();
+ LOG(FATAL) << "Creating instance for unregistered singleton: "
+ << type_.name() << "\n"
+ << "Stacktrace:"
+ << "\n" << (ptr ? (*ptr)() : "(not available)");
}
if (state_ == SingletonHolderState::Living) {
}
TEST(Singleton, MissingSingleton) {
- EXPECT_THROW([]() { auto u = Singleton<UnregisteredWatchdog>::get(); }(),
- std::out_of_range);
+ EXPECT_DEATH([]() { auto u = Singleton<UnregisteredWatchdog>::get(); }(), "");
}
struct BasicUsageTag {};
vault.registrationComplete();
// Unregistered.
- EXPECT_THROW(Singleton<Watchdog>::get(), std::out_of_range);
- EXPECT_THROW(SingletonNaughtyUsage<Watchdog>::get(), std::out_of_range);
+ EXPECT_DEATH(Singleton<Watchdog>::get(), "");
+ EXPECT_DEATH(SingletonNaughtyUsage<Watchdog>::get(), "");
vault.destroyInstances();
auto& vault2 = *SingletonVault::singleton<NaughtyUsageTag2>();
- EXPECT_THROW(SingletonNaughtyUsage2<Watchdog>::get(), std::logic_error);
+ EXPECT_DEATH(SingletonNaughtyUsage2<Watchdog>::get(), "");
SingletonNaughtyUsage2<Watchdog> watchdog_singleton;
+
// double registration
- EXPECT_THROW([]() {
- SingletonNaughtyUsage2<Watchdog> watchdog_singleton;
- }(),
- std::logic_error);
+ EXPECT_DEATH([]() { SingletonNaughtyUsage2<Watchdog> watchdog_singleton; }(),
+ "");
vault2.destroyInstances();
+
// double registration after destroy
- EXPECT_THROW([]() {
- SingletonNaughtyUsage2<Watchdog> watchdog_singleton;
- }(),
- std::logic_error);
+ EXPECT_DEATH([]() { SingletonNaughtyUsage2<Watchdog> watchdog_singleton; }(),
+ "");
}
struct SharedPtrUsageTag {};
auto& self_needy_vault = *SingletonVault::singleton<SelfNeedyTag>();
self_needy_vault.registrationComplete();
- EXPECT_THROW([]() {
- SingletonSelfNeedy<SelfNeedySingleton>::get();
- }(),
- std::out_of_range);
+ EXPECT_DEATH([]() { SingletonSelfNeedy<SelfNeedySingleton>::get(); }(), "");
}
// A test to ensure multiple threads contending on singleton creation