Ark Server API (ASA) - Wiki
Loading...
Searching...
No Matches
TypeContainer.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
6#include "Templates/PointerIsConvertibleFromTo.h"
7#include "Misc/AssertionMacros.h"
8#include "Templates/UnrealTypeTraits.h"
9#include "Containers/UnrealString.h"
10#include "Templates/Function.h"
11#include "Containers/Map.h"
12#include "Templates/SharedPointer.h"
13#include "HAL/TlsAutoCleanup.h"
14#include "Misc/ScopeLock.h"
15
16/**
17 * Enumerates the scopes for instance creation in type containers.
18 */
20{
21 /** Create a new instance each time. */
23
24 /** One singleton for the entire process. */
25 Process,
26
27 /** One singleton per thread. */
28 Thread,
29};
30
31
32/**
33 * Template for type containers.
34 *
35 * Type containers allow for configuring objects and their dependencies without actually
36 * creating these objects. They fulfill a role similar to class factories, but without
37 * being locked to a particular type of class. When passed into class constructors or
38 * methods, type containers can facilitate the Inversion of Control (IoC) pattern.
39 *
40 * Since UE neither uses run-time type information nor pre-processes plain old C++ classes,
41 * type names need to be exposed using the Expose_TNameOf macro in order to make them
42 * registrable with type containers, i.e. Expose_TNameOf(FMyClass).
43 *
44 * Once a type is registered with a container, instances of that type can be retrieved from it.
45 * There are currently three life time scopes available for instance creation:
46 *
47 * 1. Unique instance per process (aka. singleton),
48 * using RegisterClass(ETypeContainerScope::Process) or RegisterInstance()
49 * 2. Unique instance per thread (aka. thread singleton),
50 * using RegisterClass(ETypeContainerScope::Thread)
51 * 3. Unique instance per call (aka. class factory),
52 * using RegisterClass(ETypeContainerScope::Instance) or RegisterFactory()
53 *
54 * See the file TypeContainerTest.cpp for detailed examples on how to use each of these
55 * type registration methods.
56 *
57 * In the interest of fast performance, the object pointers returned by type containers are
58 * not thread-safe by default. If you intend to use the same type container and share its
59 * objects from different threads, use TTypeContainer<ESPMode::ThreadSafe> instead, which
60 * will then manage and return thread-safe versions of all object pointers.
61 *
62 * Note: Type containers depend on variadic templates and are therefore not available
63 * on XboxOne at this time, which means they should only be used for desktop applications.
64 */
65template<ESPMode Mode = ESPMode::ThreadSafe>
67{
68 /** Interface for object instance providers. */
70 {
71 public:
72
73 /** Virtual destructor. */
74 virtual ~IInstanceProvider() { }
75
76 /**
77 * Gets an instance of a class.
78 *
79 * @return Shared pointer to the instance (must be cast to TSharedPtr<R, Mode>).
80 */
81 virtual TSharedPtr<void, Mode> GetInstance() = 0;
82 };
83
84 /** Implements an instance provider that forwards instance requests to a factory function. */
85 template<class T>
87 : public IInstanceProvider
88 {
89 TFunctionInstanceProvider(TFunction<TSharedPtr<void, Mode>()>&& InCreateFunc)
91 { }
92
93 virtual ~TFunctionInstanceProvider() override { }
94
95 virtual TSharedPtr<void, Mode> GetInstance() override
96 {
97 return CreateFunc();
98 }
99
100 TFunction<TSharedPtr<void, Mode>()> CreateFunc;
101 };
102
103
104 /** Implements an instance provider that returns the same instance for all threads. */
105 template<class T>
107 : public IInstanceProvider
108 {
109 TSharedInstanceProvider(const TSharedRef<T, Mode>& InInstance)
111 { }
112
114
115 virtual TSharedPtr<void, Mode> GetInstance() override
116 {
117 return Instance;
118 }
119
121 };
122
123
124 /** Base class for per-thread instances providers. */
126 : public IInstanceProvider
127 {
128 FThreadInstanceProvider(TFunction<TSharedPtr<void, Mode>()>&& InCreateFunc)
131 { }
132
133 virtual ~FThreadInstanceProvider() override
134 {
136 }
137
138 TFunction<TSharedPtr<void, Mode>()> CreateFunc;
139 uint32 TlsSlot;
140 };
141
142
143 /** Implements an instance provider that returns the same instance per thread. */
144 template<class T>
147 {
149
150 TThreadInstanceProvider(TFunction<TSharedPtr<void, Mode>()>&& InCreateFunc)
152 { }
153
154 virtual ~TThreadInstanceProvider() override { }
155
156 virtual TSharedPtr<void, Mode> GetInstance() override
157 {
159
160 if (TlsValue == nullptr)
161 {
165 }
166
167 return TlsValue->Get();
168 }
169 };
170
171public:
172
173 /**
174 * Gets a shared pointer to an instance of the specified class.
175 *
176 * @param R The type of class to get an instance for.
177 * @param A shared reference to the instance.
178 * @see RegisterClass, RegisterDelegate, RegisterFactory, RegisterInstance
179 */
180 template<class R>
181 TSharedRef<R, Mode> GetInstance() const
182 {
184 {
187
189 }
190 }
191
192 /**
193 * Gets a shared reference to an instance of the specified class.
194 *
195 * Unlike GetInstance(), this function will assert if no instance was registered for
196 * the requested type of class using either RegisterClass() or RegisterInstance().
197 *
198 * @param R The type of class that an instance is being requested for.
199 * @param A shared pointer to the instance.
200 * @see GetInstance, RegisterClass, RegisterInstance
201 */
202 template<class R>
203 TSharedRef<R, Mode> GetInstanceRef() const
204 {
205 return GetInstance<R>().ToSharedRef();
206 }
207
208 /**
209 * Check whether the specified class has been registered.
210 *
211 * @param R The type of registered class to check.
212 * @return true if the class was registered, false otherwise.
213 */
214 template<class R>
215 bool IsRegistered() const
216 {
218 {
219 return Providers.Contains(TNameOf<R>::GetName());
220 }
221 }
222
223 /**
224 * Registers a class for instances of the specified class.
225 *
226 * @param R The type of class to register an instance class for.
227 * @param T Tye type of class to register (must be the same as or derived from R).
228 * @param P The constructor parameters that the class requires.
229 * @param Scope The scope at which instances must be unique (default = Process).
230 * @see RegisterDelegate, RegisterInstance, Unregister
231 */
232 template<class R, class T, typename... P>
234 {
235 static_assert(TPointerIsConvertibleFromTo<T, R>::Value, "T must implement R");
236
238
239 switch(Scope)
240 {
244 [this]() -> TSharedPtr<void, Mode> {
245 return MakeShareable(new T(GetInstance<P>()...));
246 }
247 )
248 );
249 break;
250
254 [this]() -> TSharedPtr<void, Mode> {
255 return MakeShareable(new T(GetInstance<P>()...));
256 }
257 )
258 );
259 break;
260
261 default:
264 MakeShareable(new T(GetInstance<P>()...))
265 )
266 );
267 break;
268 }
269
271 }
272
273 /**
274 * Register a factory delegate for the specified class.
275 *
276 * @param R The type of class to register an instance class for.
277 * @param D Tye type of factory delegate to register.
278 * @param P The parameters that the delegate requires.
279 * @param Delegate The delegate to register.
280 */
281 template<class R, class D, typename... P>
282 void RegisterDelegate(D Delegate)
283 {
284 static_assert(std::is_same_v<TSharedRef<R, Mode>, typename D::RetValType>, "Delegate return type must be TSharedPtr<R>");
285
288 [=]() -> TSharedPtr<void, Mode> {
289 return Delegate.Execute(GetInstance<P>()...);
290 }
291 )
292 );
293
295 }
296
297 /**
298 * Register a factory function for the specified class.
299 *
300 * @param R The type of class to register the instance for.
301 * @param P Additional parameters that the factory function requires.
302 * @param CreateFunc The factory function that will create instances.
303 * @see RegisterClass, RegisterInstance, Unregister
304 */
305 template<class R>
306 void RegisterFactory(const TFunction<TSharedRef<R, Mode>()>& CreateFunc)
307 {
310 [=]() -> TSharedPtr<void, Mode> {
311 return CreateFunc();
312 }
313 )
314 );
315
317 }
318
319 /**
320 * Register a factory function for the specified class.
321 *
322 * @param R The type of class to register the instance for.
323 * @param P0 The first parameter that the factory function requires.
324 * @param P Additional parameters that the factory function requires.
325 * @param CreateFunc The factory function that will create instances.
326 * @see RegisterClass, RegisterInstance, Unregister
327 */
328 template<class R, typename P0, typename... P>
329 void RegisterFactory(const TFunction<TSharedRef<R, Mode>(TSharedRef<P0, Mode>, TSharedRef<P, Mode>...)>& CreateFunc)
330 {
333 [=]() -> TSharedPtr<void, Mode> {
334 return CreateFunc(GetInstance<P0>(), GetInstance<P>()...);
335 }
336 )
337 );
338
340 }
341
342#if (defined(_MSC_VER) && _MSC_VER >= 1900) || defined(__clang__)
343 /**
344 * Register a factory function for the specified class.
345 *
346 * This is a Clang/VS2015-specific overload for handling raw function pointers.
347 *
348 * @param R The type of class to register the instance for.
349 * @param P Additional parameters that the factory function requires.
350 * @param CreateFunc The factory function that will create instances.
351 * @see RegisterClass, RegisterInstance, Unregister
352 */
353 template<class R, typename... P>
354 void RegisterFactory(TSharedRef<R, Mode> (*CreateFunc)(TSharedRef<P, Mode>...))
355 {
358 [=]() -> TSharedPtr<void, Mode> {
359 return CreateFunc(GetInstance<P>()...);
360 }
361 )
362 );
363
365 }
366#endif
367
368 /**
369 * Registers an existing instance for the specified class.
370 *
371 * @param R The type of class to register the instance for.
372 * @param T The type of the instance to register (must be the same as or derived from R).
373 * @param Instance The instance of the class to register.
374 * @see RegisterClass, RegisterDelegate, Unregister
375 */
376 template<class R, class T>
377 void RegisterInstance(const TSharedRef<T, Mode>& Instance)
378 {
379 static_assert(TPointerIsConvertibleFromTo<T, R>::Value, "T must implement R");
380
382 }
383
384 /**
385 * Unregisters the instance or class for a previously registered class.
386 *
387 * @param R The type of class to unregister.
388 * @see RegisterClass, RegisterDelegate, RegisterInstance
389 */
390 template<class R>
392 {
394 {
396 }
397 }
398
399protected:
400
401 /**
402 * Add an instance provider to the container.
403 *
404 * @param Name The name of the type to add the provider for.
405 * @param Provider The instance provider.
406 */
407 void AddProvider(const TCHAR* Name, const TSharedPtr<IInstanceProvider>& Provider)
408 {
410 {
412 }
413 }
414
415private:
416
417 /** Critical section for synchronizing access. */
419
420 /** Maps class names to instance providers. */
422};
423
424
425/** For backwards compatibility. */
#define check(expr)
ETypeContainerScope
FWindowsCriticalSection FCriticalSection
virtual TSharedPtr< void, Mode > GetInstance()=0
void RegisterFactory(const TFunction< TSharedRef< R, Mode >()> &CreateFunc)
TSharedRef< R, Mode > GetInstanceRef() const
void RegisterDelegate(D Delegate)
TSharedRef< R, Mode > GetInstance() const
void AddProvider(const TCHAR *Name, const TSharedPtr< IInstanceProvider > &Provider)
TMap< FString, TSharedPtr< IInstanceProvider > > Providers
bool IsRegistered() const
void RegisterFactory(const TFunction< TSharedRef< R, Mode >(TSharedRef< P0, Mode >, TSharedRef< P, Mode >...)> &CreateFunc)
FCriticalSection CriticalSection
void RegisterInstance(const TSharedRef< T, Mode > &Instance)
TFunction< TSharedPtr< void, Mode >()> CreateFunc
FThreadInstanceProvider(TFunction< TSharedPtr< void, Mode >()> &&InCreateFunc)
TFunction< TSharedPtr< void, Mode >()> CreateFunc
virtual TSharedPtr< void, Mode > GetInstance() override
TFunctionInstanceProvider(TFunction< TSharedPtr< void, Mode >()> &&InCreateFunc)
virtual TSharedPtr< void, Mode > GetInstance() override
TSharedInstanceProvider(const TSharedRef< T, Mode > &InInstance)
virtual TSharedPtr< void, Mode > GetInstance() override
TThreadInstanceProvider(TFunction< TSharedPtr< void, Mode >()> &&InCreateFunc)
TTlsAutoCleanupValue< TSharedPtr< T, Mode > > TlsValueType