creating_thread_.store(std::this_thread::get_id(), std::memory_order_release);
auto state = vault_.state_.rlock();
+ if (vault_.type_ != SingletonVault::Type::Relaxed &&
+ !state->registrationComplete) {
+ 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. " << stack_trace;
+ }
if (state->state == SingletonVault::SingletonVaultState::Quiescing) {
return;
}
#include <folly/Singleton.h>
+#ifndef _WIN32
+#include <dlfcn.h>
+#endif
+
#include <atomic>
#include <cstdio>
#include <cstdlib>
#include <folly/ScopeGuard.h>
+#if !defined(_WIN32) && !defined(__APPLE__)
+static void hs_init_weak(int* argc, char** argv[])
+ __attribute__((__weakref__("hs_init")));
+#endif
+
namespace folly {
+SingletonVault::Type SingletonVault::defaultVaultType() {
+#if !defined(_WIN32) && !defined(__APPLE__)
+ bool isPython = dlsym(RTLD_DEFAULT, "Py_Main");
+ bool isHaskel = &::hs_init_weak || dlsym(RTLD_DEFAULT, "hs_init");
+ bool isJVM = dlsym(RTLD_DEFAULT, "JNI_GetCreatedJavaVMs");
+ bool isD = dlsym(RTLD_DEFAULT, "_d_run_main");
+
+ return isPython || isHaskel || isJVM || isD ? Type::Relaxed : Type::Strict;
+#else
+ return Type::Relaxed;
+#endif
+}
+
namespace detail {
[[noreturn]] void singletonWarnDoubleRegistrationAndAbort(
}
};
- explicit SingletonVault(Type type = Type::Strict) : type_(type) {}
+ static Type defaultVaultType();
+
+ explicit SingletonVault(Type type = defaultVaultType()) : type_(type) {}
// Destructor is only called by unit tests to check destroyInstances.
~SingletonVault();