13#include "CoreMinimal.h"
31 template <CDefaultInitializable = T>
34 template <CMoveConstructible = T>
37 template <CCopyConstructible = T>
40 template <CMoveConstructible = T>
43 template <
typename Arg>
44 requires (!CSameAs<Arg, TChangeData> && !CSameAs<Arg, T>)
47 template <
typename... Args>
48 requires (
sizeof...(Args) > 1)
71 virtual T
const&
Get()
const = 0;
81 virtual void Set(T
const& value) = 0;
93 virtual void Modify(TUniqueFunction<
void(T&)>&& modifier,
bool alwaysNotify =
true) = 0;
96 template <CChangeListener<T> Function>
102 onChange(change.Next);
104 onChange(change.Next, change.Previous);
125 template <CChangeListener<T> Function>
139 template <
typename Object, CChangeListener<T> Function>
156 template <CConvertibleToDecayed<T> Other,
typename Guard>
161 [
this](Other
const& next) {
Set(next); },
177 template <
typename Other,
typename Guard>
178 requires CConvertibleToDecayed<Other, T>
183 [&otherState](T
const& next) { otherState.
Set(next); },
203 virtual bool Remove(FDelegateHandle
const& handle) = 0;
226 virtual TTuple<T const&, TUniquePtr<ReadLockVariant>>
GetOnAnyThread()
const = 0;
235 virtual TUniquePtr<ReadLockVariant>
ReadLock()
const = 0;
278 template <CBooleanTestable = T>
285 return static_cast<bool>(
Get()) && !previous;
293 template <CBooleanTestable = T>
301 template <CBooleanTestable = T>
308 return !
static_cast<bool>(
Get()) && previous;
316 template <CBooleanTestable = T>
320 template <CCoreEqualityComparable = T>
327 template <CCoreEqualityComparable = T>
333 template <
typename Self>
334 operator T
const& (
this Self&& self)
339 template <
typename Self>
366 template <
typename T, FStatePolicy DefaultPolicy>
369 template <
typename ThreadSafeType,
typename NaiveType>
370 using ThreadSafeSwitch = std::conditional_t<DefaultPolicy.ThreadSafe, ThreadSafeType, NaiveType>;
383 template <CDefaultInitializable = T>
387 template <CCopyConstructible = T>
388 explicit TState(T
const& value) : Value(value) {}
391 template <CMoveConstructible = T>
392 explicit TState(T&& value) : Value(MoveTemp(value)) {}
395 template <CCopyConstructible = T>
399 template <CMoveConstructible = T>
403 template <
typename Arg>
404 requires (!CConvertibleTo<Arg, TState> && !CSameAs<Arg, T>)
408 template <
typename... Args>
409 requires (
sizeof...(Args) > 1)
412 virtual T
const&
Get()
const override {
return Value.Next; }
414 virtual TTuple<T const&, TUniquePtr<ReadLockVariant>>
GetOnAnyThread()
const override
419 virtual void Set(T
const& value)
override
422 ->WithMessage(
TEXT_"Attempting to set this state while this state is already being set from somewhere else.")
424 TGuardValue modifyingGuard(Modifying,
true);
428 if constexpr (CCoreEqualityComparable<T>)
431 if constexpr (CCopyable<T>)
433 Value.Previous = Value.Next;
438 OnChangeEvent.Broadcast(Value);
442 virtual void Modify(TUniqueFunction<
void(T&)>&& modifier,
bool alwaysNotify =
true)
override
445 ->WithMessage(
TEXT_"Attempting to set this state while this state is already being set from somewhere else.")
447 TGuardValue modifyingGuard(Modifying,
true);
450 TOptional<T> previous;
452 if constexpr (CCopyable<T>)
454 previous = Value.Next;
456 modifier(Value.Next);
458 if constexpr (CCopyable<T> && CCoreEqualityComparable<T>)
461 || !Value.Previous.IsSet()
462 || previous.GetValue() != Value.Next;
464 if constexpr (CCopyable<T>)
466 Value.Previous = previous;
469 OnChangeEvent.Broadcast(Value);
476 return OnChangeEvent.Add(onChange, eventPolicy);
480 virtual bool Remove(FDelegateHandle
const& handle)
override
483 return OnChangeEvent.Remove(handle);
489 return OnChangeEvent.RemoveAll(
object);
494 if constexpr (CCoreEqualityComparable<T>)
496 bool hasChanged = Value.Next != nextValue;
509 return OnChangeEvent.IsBroadcasted();
512 virtual TUniquePtr<ReadLockVariant>
ReadLock()
const override
514 return MakeUnique<ReadLockVariant>(TInPlaceType<ReadLockType>(), Mutex.
Get());
517 virtual TUniquePtr<WriteLockVariant>
WriteLock()
override
519 return MakeUnique<WriteLockVariant>(TInPlaceType<WriteLockType>(), Mutex.
Get());
524 return Value.Previous;
529 return Value.Previous.Get(fallback);
534 return Value.Previous.IsSet() ? Value.Previous.GetValue() : Value.Next;
541 ->WithMessage(
TEXT_"Attempting to set this state while this state is already being set from somewhere else.")
543 TGuardValue modifyingGuard(Modifying,
true);
545 Value.Previous = Value.Next;
548 template <CConvertibleTo<T> Other>
552 if constexpr (CCopyable<Other>)
554 else if constexpr (CMovable<Other>)
555 Set(MoveTemp(value));
564 bool Modifying =
false;
568 template <
typename LeftValue, CWeaklyEqualityComparableWith<LeftValue> RightValue>
571 return left.
Get() == right.
Get();
574 template <
typename LeftValue, CPartiallyOrderedWith<LeftValue> RightValue>
577 return left.
Get() <=> right.
Get();
#define ASSERT_QUIT(condition, returnOnFailure,...)
Use this instead of check macro if the checked expression shouldn't be ignored in shipping builds....
#define FWD(...)
Shorten forwarding expression with this macro so one may not need to specify explicit type.
#define TEXT_
A convenience alternative to Unreal's own TEXT macro but this one doesn't require parenthesis around ...
"Extension" of a common TMulticastDelegate. It allows to define optional "flags" when adding a bindin...
Concept describing a function which can listen to changes to the current value of a TState only.
Concept describing a function which can listen to changes to the current and the previous values of a...
Concept constraining given type to a state.
TInferredDelegate< Function, Captures... > From(Function func, Captures &&... captures)
Instead of specifying manually a delegate type, infer it from the input function and the extra captur...
bool operator==(IState< LeftValue > const &left, IState< RightValue > const &right)
bool operator<=>(IState< LeftValue > const &left, IState< RightValue > const &right)
Settings for the TEventDelegate class, which defines optional behavior when adding a binding to it.
A type wrapper around a default initializeable object which may not be copyable but which needs to be...
Flags expressing how TState should handle object comparison and lifespan.
bool StorePrevious
Store previous value as well. If the value is equality comparable store only when it's changed.
bool AlwaysStorePrevious
If the state value is equality comparable, store the previous value even when that's equal to the new...
bool AlwaysNotify
Always emit change notification when a value is set on TState and don't attempt to compare them.
Public API and base class for TState which shouldn't concern with policy flags or thread safety.
virtual T const & GetPreviousOrCurrent() const =0
Get the previous value if StorePrevious is enabled and there was at least one change or the current v...
bool HasChanged(T const &fallback) const
Returns true when current value is not equal to previous one.
virtual void NormalizePrevious()=0
Set the previous value to the current one. Useful in Ticks.
virtual int32 RemoveAll(const void *object)=0
Equivalent to TMulticastDelegate::RemoveAll
FDelegateHandle OnChange(TDelegate< void(TChangeData< T > const &)> onChange, FEventPolicy const &eventPolicy={})
Add a delegate which gets a TChangeData<T> const& if this state has been set.
virtual void Set(T const &value)=0
Set the wrapped value if for some reason the assignment operator is not enough or deleted....
virtual bool HasEverChanged() const =0
Returns true if this state has ever been changed from its initial value given at construction.
bool OnDown(bool fallback=false) const
Returns true when this state is currently true, but previously it wasn't.
bool BecameTrue(bool fallback=false) const
Returns true when this state is currently true, but previously it wasn't.
virtual void Modify(TUniqueFunction< void(T &)> &&modifier, bool alwaysNotify=true)=0
Modify this state via an l-value ref in a functor.
TVariant< FWriteScopeLock, FVoid > WriteLockVariant
virtual TOptional< T > const & GetPrevious() const =0
Get the previous value if StorePrevious is enabled and there was at least one change.
bool BecameFalse(bool fallback=false) const
Returns true when this state is currently false, but previously it wasn't.
virtual bool Remove(FDelegateHandle const &handle)=0
Equivalent to TMulticastDelegate::Remove
virtual T const & GetPrevious(T const &fallback) const =0
Get the previous value if StorePrevious is enabled and there was at least one change....
virtual bool HasChangedFrom(const T &nextValue)=0
Given value will be stored in the state only if T is equality comparable and it differs from the curr...
virtual T const & Get() const =0
Get the wrapped value if for some reason the conversion operator is not enough or deleted....
const T * operator->(this Self &&self)
bool OnUp(bool fallback=false) const
Returns true when this state is currently false, but previously it wasn't.
virtual FDelegateHandle OnChangeImpl(TDelegate< void(TChangeData< T > const &)> &&onChange, FEventPolicy const &eventPolicy={})=0
void SyncPull(Guard &&object, IState< Other > &otherState)
Pull changes from another state, syncing the value between the two. Values will be copied.
FDelegateHandle OnChange(Function const &onChange, FEventPolicy const &eventPolicy={})
Add a function without object binding which either has one or two arguments with the following signat...
FDelegateHandle OnChange(Object &&object, Function const &onChange, FEventPolicy const &eventPolicy={})
Add a function with an object binding which either has one or two arguments with the following signat...
void SyncPush(Guard &&object, IState< Other > &otherState)
Push changes from another state, syncing the value between the two. Values will be copied.
virtual TUniquePtr< ReadLockVariant > ReadLock() const =0
Lock this state for reading for the current scope.
bool HasChanged() const
Returns true when current value is not equal to previous one.
TVariant< FReadScopeLock, FVoid > ReadLockVariant
virtual TTuple< T const &, TUniquePtr< ReadLockVariant > > GetOnAnyThread() const =0
If thread safety is enabled in DefaultPolicy, get the value with a bundled read-scope-lock....
static auto DelegateValueArgument(Function const &onChange)
virtual TUniquePtr< WriteLockVariant > WriteLock()=0
Lock this state for writing for the current scope.
virtual ~IState()=default
This struct holds the circumstances of the data change. It cannot be moved or copied and its lifespan...
TChangeData(Args &&... args)
TChangeData(const TChangeData &from)
TChangeData(TChangeData &&from) noexcept
Storage wrapper for any value which state needs to be tracked or their change needs to be observed....
virtual TUniquePtr< WriteLockVariant > WriteLock() override
Lock this state for writing for the current scope.
TState(T &&value)
Enable move constructor for T only when T is move constructable.
virtual int32 RemoveAll(const void *object) override
Equivalent to TMulticastDelegate::RemoveAll
virtual void Set(T const &value) override
Set the wrapped value if for some reason the assignment operator is not enough or deleted....
std::conditional_t< DefaultPolicy.ThreadSafe, ThreadSafeType, NaiveType > ThreadSafeSwitch
virtual FDelegateHandle OnChangeImpl(TDelegate< void(TChangeData< T > const &)> &&onChange, FEventPolicy const &eventPolicy={}) override
virtual bool Remove(FDelegateHandle const &handle) override
Equivalent to TMulticastDelegate::Remove
TState(TState const &other)
Enable copy constructor for the state only when T is copy constructable.
virtual void Modify(TUniqueFunction< void(T &)> &&modifier, bool alwaysNotify=true) override
Modify this state via an l-value ref in a functor.
virtual T const & GetPreviousOrCurrent() const override
Get the previous value if StorePrevious is enabled and there was at least one change or the current v...
static constexpr FStatePolicy DefaultPolicyFlags
virtual TUniquePtr< ReadLockVariant > ReadLock() const override
Lock this state for reading for the current scope.
virtual T const & GetPrevious(T const &fallback) const override
Get the previous value if StorePrevious is enabled and there was at least one change....
TState(Arg &&arg)
Construct value in-place with non-semantic single argument constructor.
TState()
Enable default constructor only when T is default initializable.
virtual TTuple< T const &, TUniquePtr< ReadLockVariant > > GetOnAnyThread() const override
If thread safety is enabled in DefaultPolicy, get the value with a bundled read-scope-lock....
virtual bool HasChangedFrom(const T &nextValue) override
Given value will be stored in the state only if T is equality comparable and it differs from the curr...
ThreadSafeSwitch< FReadScopeLock, FVoid > ReadLockType
virtual TOptional< T > const & GetPrevious() const override
Get the previous value if StorePrevious is enabled and there was at least one change.
ThreadSafeSwitch< FWriteScopeLock, FVoid > WriteLockType
virtual void NormalizePrevious() override
Set the previous value to the current one. Useful in Ticks.
TState(Args &&... args)
Construct value in-place with multiple argument constructor.
TState(TState &&other)
Enable move constructor for the state only when T is move constructable.
virtual T const & Get() const override
Get the wrapped value if for some reason the conversion operator is not enough or deleted....
TState(T const &value)
Enable copy constructor for T only when T is copy constructable.
virtual bool HasEverChanged() const override
Returns true if this state has ever been changed from its initial value given at construction.