Ark Server API (ASA) - Wiki
Loading...
Searching...
No Matches
LazySingleton.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include <new> // IWYU pragma: export
6
7/** Allows inline friend declaration without forward-declaring TLazySingleton */
9{
10protected:
11 template<class T> static void Construct(void* Place) { new (Place) T; }
12 template<class T> static void Destruct(T* Instance) { Instance->~T(); }
13};
14
15/**
16 * Lazy singleton that can be torn down explicitly
17 *
18 * Defining DISABLE_LAZY_SINGLETON_DESTRUCTION stops automatic static destruction
19 * and will instead leak singletons that have not been explicitly torn down.
20 * This helps prevent shutdown crashes and deadlocks in quick exit scenarios
21 * such as ExitProcess() on Windows.
22 *
23 * T must be default constructible.
24 *
25 * Example use case:
26 *
27 * struct FOo
28 * {
29 * static FOo& Get();
30 * static void TearDown();
31 *
32 * // If default constructor is private
33 * friend class FLazySingleton;
34 * };
35 *
36 * // Only include in .cpp and do *not* inline Get() and TearDown()
37 * #include "Misc/LazySingleton.h"
38 *
39 * FOo& FOo::Get()
40 * {
41 * return TLazySingleton<FOo>::Get();
42 * }
43 *
44 * void FOo::TearDown()
45 * {
46 * TLazySingleton<FOo>::TearDown();
47 * }
48 */
49template<class T>
50class TLazySingleton final : public FLazySingleton
51{
52public:
53 /**
54 * Creates singleton once on first call.
55 * Thread-safe w.r.t. other Get() calls.
56 * Do not call after TearDown().
57 */
58 static T& Get()
59 {
60 return GetLazy(Construct<T>).GetValue();
61 }
62
63 /** Destroys singleton. No thread must access the singleton during or after this call. */
64 static void TearDown()
65 {
66 return GetLazy(nullptr).Reset();
67 }
68
69 /** Get or create singleton unless it's torn down */
70 static T* TryGet()
71 {
72 return GetLazy(Construct<T>).TryGetValue();
73 }
74
75private:
76 static TLazySingleton& GetLazy(void(*Constructor)(void*))
77 {
78 static TLazySingleton Singleton(Constructor);
79 return Singleton;
80 }
81
82 alignas(T) unsigned char Data[sizeof(T)];
83 T* Ptr;
84
85 TLazySingleton(void(*Constructor)(void*))
86 {
87 if (Constructor)
88 {
89 Constructor(Data);
90 }
91
92 Ptr = Constructor ? (T*)Data : nullptr;
93 }
94
95#if (!defined(DISABLE_LAZY_SINGLETON_DESTRUCTION) || !DISABLE_LAZY_SINGLETON_DESTRUCTION)
97 {
98 Reset();
99 }
100#endif
101
103 {
104 return Ptr;
105 }
106
108 {
109 check(Ptr);
110 return *Ptr;
111 }
112
113 void Reset()
114 {
115 if (Ptr)
116 {
117 Destruct(Ptr);
118 Ptr = nullptr;
119 }
120 }
121};
static void Destruct(T *Instance)
static void Construct(void *Place)
TLazySingleton(void(*Constructor)(void *))
static void TearDown()
static T & Get()
static T * TryGet()
static TLazySingleton & GetLazy(void(*Constructor)(void *))
unsigned char Data[sizeof(T)]