2023-01-02 13:49:24 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "CoreTypes.h"
|
|
|
|
#include "Templates/Utility.h"
|
|
|
|
#include "TypeTraits/Invocable.h"
|
|
|
|
#include "Templates/Noncopyable.h"
|
|
|
|
#include "TypeTraits/CompositeType.h"
|
|
|
|
#include "TypeTraits/Miscellaneous.h"
|
|
|
|
#include "TypeTraits/SupportedOperations.h"
|
|
|
|
|
|
|
|
NAMESPACE_REDCRAFT_BEGIN
|
|
|
|
NAMESPACE_MODULE_BEGIN(Redcraft)
|
|
|
|
NAMESPACE_MODULE_BEGIN(Utility)
|
|
|
|
|
|
|
|
/** The class template is a general-purpose scope guard intended to call its callback function when a scope is exited. */
|
|
|
|
template <CInvocable F> requires (CDestructible<F>)
|
2023-01-03 11:22:06 +00:00
|
|
|
class TScopeCallback final : private FNoncopyable
|
2023-01-02 13:49:24 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
/** Initializes the callback function with a function or function object. */
|
|
|
|
template <typename InF> requires (!CSameAs<TRemoveCVRef<InF>, TScopeCallback> && CConstructibleFrom<F, InF>)
|
|
|
|
FORCEINLINE constexpr explicit TScopeCallback(InF&& Func) : Storage(Forward<InF>(Func)), bIsActive(true) { }
|
|
|
|
|
|
|
|
/** Move constructor. Initializes the stored object with the one in other. */
|
|
|
|
FORCEINLINE constexpr TScopeCallback(TScopeCallback&& InValue) requires (CMoveConstructible<F>)
|
|
|
|
: Storage(MoveTemp(InValue.Storage)), bIsActive(InValue.bIsActive)
|
|
|
|
{
|
|
|
|
InValue.Release();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Calls the callback function if the TScopeCallback is active, then destroys the stored object. */
|
|
|
|
FORCEINLINE constexpr ~TScopeCallback()
|
|
|
|
{
|
|
|
|
if (bIsActive) Storage();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Makes the TScopeCallback inactive. */
|
|
|
|
FORCEINLINE constexpr void Release() { bIsActive = false; }
|
|
|
|
|
|
|
|
/** @return a const reference to the stored object. */
|
|
|
|
FORCEINLINE constexpr const F& Get() const { return Storage; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
F Storage;
|
|
|
|
bool bIsActive;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename F>
|
|
|
|
TScopeCallback(F) -> TScopeCallback<F>;
|
|
|
|
|
|
|
|
/** The class template is a general-purpose scope guard intended to make sure a value is restored when a scope is exited. */
|
|
|
|
template <typename T> requires (CCopyConstructible<T> && CCopyAssignable<T> && CMoveAssignable<T> && CDestructible<T>)
|
2023-01-03 11:22:06 +00:00
|
|
|
class TGuardValue final : private FNoncopyable
|
2023-01-02 13:49:24 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
/** Initializes the TGuardValue with a reference. */
|
|
|
|
FORCEINLINE constexpr TGuardValue(T& InReference) : Reference(InReference), OldValue(InReference), bIsActive(true) { }
|
|
|
|
|
|
|
|
/** Initializes the TGuardValue with a reference and assign a new value to the reference. */
|
|
|
|
template <typename U> requires (CAssignableFrom<T&, U>)
|
|
|
|
FORCEINLINE constexpr TGuardValue(T& InReference, U&& InValue) : Reference(InReference), OldValue(InReference), bIsActive(true) { InReference = InValue; }
|
|
|
|
|
|
|
|
/** Move constructor. Initializes the referenced value and old value with the one in other. */
|
|
|
|
FORCEINLINE constexpr TGuardValue(TGuardValue&& InValue) requires (CMoveConstructible<T>)
|
|
|
|
: Reference(InValue.Reference), OldValue(MoveTemp(InValue.OldValue)), bIsActive(InValue.bIsActive)
|
|
|
|
{
|
|
|
|
InValue.Release();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Restore the referenced value if the TGuardValue is active, then destroys the old value. */
|
|
|
|
FORCEINLINE constexpr ~TGuardValue()
|
|
|
|
{
|
|
|
|
if (bIsActive) Reference = MoveTemp(OldValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Makes the TGuardValue inactive. */
|
|
|
|
FORCEINLINE constexpr void Release() { bIsActive = false; }
|
|
|
|
|
|
|
|
/** @return a const reference to the old value. */
|
|
|
|
FORCEINLINE constexpr const T& Get() const { return OldValue; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
T& Reference;
|
|
|
|
T OldValue;
|
|
|
|
bool bIsActive;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
TGuardValue(T&) -> TGuardValue<T>;
|
|
|
|
|
|
|
|
template <typename T, typename U>
|
|
|
|
TGuardValue(T&, U&&) -> TGuardValue<T>;
|
|
|
|
|
|
|
|
/** Commonly used to make sure a value is incremented, and then decremented when a scope is exited. */
|
|
|
|
template <typename T> requires (requires(T& Value) { ++Value; --Value; })
|
2023-01-03 11:22:06 +00:00
|
|
|
class TScopeCounter final : private FNoncopyable
|
2023-01-02 13:49:24 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
/** Initializes the TScopeCounter with a reference and increments it. */
|
|
|
|
FORCEINLINE constexpr TScopeCounter(T& InReference)
|
|
|
|
: Reference(InReference)
|
|
|
|
{
|
|
|
|
++Reference;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Decrements the referenced value. */
|
|
|
|
FORCEINLINE constexpr ~TScopeCounter()
|
|
|
|
{
|
|
|
|
--Reference;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @return a const reference to the value. */
|
|
|
|
FORCEINLINE constexpr const T& Get() const { return Reference; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
T& Reference;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
TScopeCounter(T&) -> TScopeCounter<T>;
|
|
|
|
|
|
|
|
NAMESPACE_MODULE_END(Utility)
|
|
|
|
NAMESPACE_MODULE_END(Redcraft)
|
|
|
|
NAMESPACE_REDCRAFT_END
|