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.
This commit is contained in:
Tom 2021-01-08 12:01:53 -07:00 committed by Andreas Kling
parent 8548ec357c
commit 1fc7d65aad
Notes: sideshowbarker 2024-07-18 23:58:56 +09:00

View file

@ -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) {
#ifdef KERNEL
Kernel::Processor::wait_check();
#else
// TODO: yield
#endif
obj = AK::atomic_load(&m_obj, AK::memory_order_consume);
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;
}
}
// We should always return an instance
ASSERT(obj != nullptr);
// Someone else was faster, wait until they're done
while (obj == (T*)0x1) {
#ifdef KERNEL
Kernel::Processor::wait_check();
#else
// TODO: yield
#endif
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);
}
ASSERT(obj != (T*)0x1);
}
return obj;
}
T* ptr() const
{
return get(m_obj);
}
T* operator->() const
{
return ptr();