summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2021-01-08 12:01:53 -0700
committerAndreas Kling <kling@serenityos.org>2021-01-09 21:12:31 +0100
commit1fc7d65aadedb8ec421e788d07e6c00ee023c06b (patch)
treeb5ae7e1dc402774591c777006bb2ceb63d8c26c8
parent8548ec357cb28a1dab79635e4c99408de28c353a (diff)
downloadserenity-1fc7d65aadedb8ec421e788d07e6c00ee023c06b.zip
AK: Add static Singleton::get function to allow destructible globals
This enable using global raw pointers rather than Singleton objects, which solves some problems because global Singleton object could be deleted when destructors are run.
-rw-r--r--AK/Singleton.h40
1 files changed, 25 insertions, 15 deletions
diff --git a/AK/Singleton.h b/AK/Singleton.h
index da1305e1c5..615171b855 100644
--- a/AK/Singleton.h
+++ b/AK/Singleton.h
@@ -56,36 +56,46 @@ class Singleton {
public:
Singleton() = default;
- T* ptr() const
+ template<bool allow_create = true>
+ static T* get(T*& obj_var)
{
- T* obj = AK::atomic_load(&m_obj, AK::memory_order_consume);
+ T* obj = AK::atomic_load(&obj_var, AK::memory_order_acquire);
if (FlatPtr(obj) <= 0x1) {
// If this is the first time, see if we get to initialize it
#ifdef KERNEL
Kernel::ScopedCritical critical;
#endif
- if (obj == nullptr && AK::atomic_compare_exchange_strong(&m_obj, obj, (T*)0x1, AK::memory_order_acq_rel)) {
- // We're the first one
- obj = InitFunction();
- AK::atomic_store(&m_obj, obj, AK::memory_order_release);
- } else {
- // Someone else was faster, wait until they're done
- while (obj == (T*)0x1) {
+ if constexpr (allow_create) {
+ if (obj == nullptr && AK::atomic_compare_exchange_strong(&obj_var, obj, (T*)0x1, AK::memory_order_acq_rel)) {
+ // We're the first one
+ obj = InitFunction();
+ AK::atomic_store(&obj_var, obj, AK::memory_order_release);
+ return obj;
+ }
+ }
+ // Someone else was faster, wait until they're done
+ while (obj == (T*)0x1) {
#ifdef KERNEL
- Kernel::Processor::wait_check();
+ Kernel::Processor::wait_check();
#else
- // TODO: yield
+ // TODO: yield
#endif
- obj = AK::atomic_load(&m_obj, AK::memory_order_consume);
- }
+ obj = AK::atomic_load(&obj_var, AK::memory_order_acquire);
+ }
+ if constexpr (allow_create) {
+ // We should always return an instance if we allow creating one
+ ASSERT(obj != nullptr);
}
- // We should always return an instance
- ASSERT(obj != nullptr);
ASSERT(obj != (T*)0x1);
}
return obj;
}
+ T* ptr() const
+ {
+ return get(m_obj);
+ }
+
T* operator->() const
{
return ptr();