diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:34:54 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:34:54 +0000 |
commit | 0915b3ef56dfac3113cce55a59a5765dc94976be (patch) | |
tree | a8fea11d50b4f083e1bf0f90025ece7f0824784a /lib/base/lazy-init.hpp | |
parent | Initial commit. (diff) | |
download | icinga2-0915b3ef56dfac3113cce55a59a5765dc94976be.tar.xz icinga2-0915b3ef56dfac3113cce55a59a5765dc94976be.zip |
Adding upstream version 2.13.6.upstream/2.13.6upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'lib/base/lazy-init.hpp')
-rw-r--r-- | lib/base/lazy-init.hpp | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/lib/base/lazy-init.hpp b/lib/base/lazy-init.hpp new file mode 100644 index 0000000..c1da2cd --- /dev/null +++ b/lib/base/lazy-init.hpp @@ -0,0 +1,72 @@ +/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */ + +#ifndef LAZY_INIT +#define LAZY_INIT + +#include <atomic> +#include <functional> +#include <mutex> +#include <utility> + +namespace icinga +{ + +/** + * Lazy object initialization abstraction inspired from + * <https://docs.microsoft.com/en-us/dotnet/api/system.lazy-1?view=netframework-4.7.2>. + * + * @ingroup base + */ +template<class T> +class LazyInit +{ +public: + inline + LazyInit(std::function<T()> initializer = []() { return T(); }) : m_Initializer(std::move(initializer)) + { + m_Underlying.store(nullptr, std::memory_order_release); + } + + LazyInit(const LazyInit&) = delete; + LazyInit(LazyInit&&) = delete; + LazyInit& operator=(const LazyInit&) = delete; + LazyInit& operator=(LazyInit&&) = delete; + + inline + ~LazyInit() + { + auto ptr (m_Underlying.load(std::memory_order_acquire)); + + if (ptr != nullptr) { + delete ptr; + } + } + + inline + T& Get() + { + auto ptr (m_Underlying.load(std::memory_order_acquire)); + + if (ptr == nullptr) { + std::unique_lock<std::mutex> lock (m_Mutex); + + ptr = m_Underlying.load(std::memory_order_acquire); + + if (ptr == nullptr) { + ptr = new T(m_Initializer()); + m_Underlying.store(ptr, std::memory_order_release); + } + } + + return *ptr; + } + +private: + std::function<T()> m_Initializer; + std::mutex m_Mutex; + std::atomic<T*> m_Underlying; +}; + +} + +#endif /* LAZY_INIT */ |