summaryrefslogtreecommitdiff
path: root/AK
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-04-03 16:50:08 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-04-03 16:52:25 +0200
commitc02c9880b61569455eeea1dacaa15d29c33021ea (patch)
tree35580c7110f28edd9ef5b41a043f38619c0f96f1 /AK
parent528054d192448f93789fedc3782550b3a80bee27 (diff)
downloadserenity-c02c9880b61569455eeea1dacaa15d29c33021ea.zip
AK: Add Eternal<T> and use it in various places.
This is useful for static locals that never need to be destroyed: Thing& Thing::the() { static Eternal<Thing> the; return the; } The object will be allocated in data segment memory and will never have its destructor invoked.
Diffstat (limited to 'AK')
-rw-r--r--AK/Eternal.h30
-rw-r--r--AK/kmalloc.h1
2 files changed, 31 insertions, 0 deletions
diff --git a/AK/Eternal.h b/AK/Eternal.h
new file mode 100644
index 0000000000..6db63a300f
--- /dev/null
+++ b/AK/Eternal.h
@@ -0,0 +1,30 @@
+#pragma once
+
+#include <AK/StdLibExtras.h>
+
+namespace AK {
+
+template<typename T>
+class Eternal {
+public:
+ template<typename... Args>
+ Eternal(Args&&... args)
+ {
+ new (m_slot) T(forward<Args>(args)...);
+ }
+
+ T& get() { return *reinterpret_cast<T*>(&m_slot); }
+ const T& get() const { return *reinterpret_cast<T*>(&m_slot); }
+ T* operator->() { return &get(); }
+ const T* operator->() const { return &get(); }
+ operator T&() { return get(); }
+ operator const T&() const { return get(); }
+
+
+private:
+ [[gnu::aligned(alignof(T))]] char m_slot[sizeof(T)];
+};
+
+}
+
+using AK::Eternal;
diff --git a/AK/kmalloc.h b/AK/kmalloc.h
index 3b28b0a4f4..d6a5966e3d 100644
--- a/AK/kmalloc.h
+++ b/AK/kmalloc.h
@@ -8,6 +8,7 @@
#define AK_MAKE_ETERNAL \
public: \
void* operator new(size_t size) { return kmalloc_eternal(size); } \
+ void* operator new(size_t, void* ptr) { return ptr; } \
private:
#else
#define AK_MAKE_ETERNAL