MCRO
C++23 utilities for Unreal Engine.
Loading...
Searching...
No Matches
Mcro::Observable::TState< T, DefaultPolicy > Struct Template Reference

Storage wrapper for any value which state needs to be tracked or their change needs to be observed. By default, TState is not thread-safe unless FStatePolicy::ThreadSafe policy is active in DefaultPolicy. More...

#include <Observable.h>

Inheritance diagram for Mcro::Observable::TState< T, DefaultPolicy >:
Mcro::Observable::IState< T > Mcro::Observable::IStateTag

Public Types

template<typename ThreadSafeType , typename NaiveType >
using ThreadSafeSwitch = std::conditional_t<DefaultPolicy.ThreadSafe, ThreadSafeType, NaiveType>
 
using StateBase = IState<T>
 
using ReadLockType = ThreadSafeSwitch<FReadScopeLock, FVoid>
 
using WriteLockType = ThreadSafeSwitch<FWriteScopeLock, FVoid>
 
using ReadLockVariant
 
using WriteLockVariant
 
- Public Types inherited from Mcro::Observable::IState< T >
using Type = T
 
using ReadLockVariant = TVariant<FReadScopeLock, FVoid>
 
using WriteLockVariant = TVariant<FWriteScopeLock, FVoid>
 

Public Member Functions

template<CDefaultInitializable = T>
 TState ()
 Enable default constructor only when T is default initializable.
 
template<CCopyConstructible = T>
 TState (T const &value)
 Enable copy constructor for T only when T is copy constructable.
 
template<CMoveConstructible = T>
 TState (T &&value)
 Enable move constructor for T only when T is move constructable.
 
template<CCopyConstructible = T>
 TState (TState const &other)
 Enable copy constructor for the state only when T is copy constructable.
 
template<CMoveConstructible = T>
 TState (TState &&other)
 Enable move constructor for the state only when T is move constructable.
 
template<typename Arg >
requires (!CConvertibleTo<Arg, TState> && !CSameAs<Arg, T>)
 TState (Arg &&arg)
 Construct value in-place with non-semantic single argument constructor.
 
template<typename... Args>
requires (sizeof...(Args) > 1)
 TState (Args &&... args)
 Construct value in-place with multiple argument constructor.
 
virtual T const & Get () const override
 Get the wrapped value if for some reason the conversion operator is not enough or deleted. Thread safety is not considered in this function, use ReadLock before Get, or use GetOnAnyThread which provides a read lock, if thread safety is a concern.
 
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. Otherwise the tuple returns an empty dummy struct as its second argument.
 
virtual void Set (T const &value) override
 Set the wrapped value if for some reason the assignment operator is not enough or deleted. When thread safety is enabled Set will automatically lock this state for writing.
 
virtual void Modify (TUniqueFunction< void(T &)> &&modifier, bool alwaysNotify=true) override
 Modify this state via an l-value ref in a functor.
 
virtual bool Remove (FDelegateHandle const &handle) override
 Equivalent to TMulticastDelegate::Remove
 
virtual int32 RemoveAll (const void *object) override
 Equivalent to TMulticastDelegate::RemoveAll
 
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 current state value. If T is not equality comparable this function is equivalent to Set and always returns true.
 
virtual bool HasEverChanged () const override
 Returns true if this state has ever been changed from its initial value given at construction.
 
virtual TUniquePtr< ReadLockVariantReadLock () const override
 Lock this state for reading for the current scope.
 
virtual TUniquePtr< WriteLockVariantWriteLock () override
 Lock this state for writing for the current scope.
 
virtual TOptional< T > const & GetPrevious () const override
 Get the previous value if StorePrevious is enabled and there was at least one change.
 
virtual T const & GetPrevious (T const &fallback) const override
 Get the previous value if StorePrevious is enabled and there was at least one change. Get a fallback value otherwise.
 
virtual T const & GetPreviousOrCurrent () const override
 Get the previous value if StorePrevious is enabled and there was at least one change or the current value otherwise.
 
virtual void NormalizePrevious () override
 Set the previous value to the current one. Useful in Ticks.
 
template<CConvertibleTo< T > Other>
requires (!CState<Other>)
TStateoperator= (Other &&value)
 
- Public Member Functions inherited from Mcro::Observable::IState< T >
virtual ~IState ()=default
 
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.
 
template<CChangeListener< T > Function>
FDelegateHandle OnChange (Function const &onChange, FEventPolicy const &eventPolicy={})
 Add a function without object binding which either has one or two arguments with the following signature: [](T const& next, [TOptional<T> const& previous])
 
template<typename Object , CChangeListener< T > Function>
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 signature: [](T const& next, [TOptional<T> const& previous])
 
template<CConvertibleToDecayed< T > Other, typename Guard >
void SyncPull (Guard &&object, IState< Other > &otherState)
 Pull changes from another state, syncing the value between the two. Values will be copied.
 
template<typename Other , typename Guard >
requires CConvertibleToDecayed<Other, T>
void SyncPush (Guard &&object, IState< Other > &otherState)
 Push changes from another state, syncing the value between the two. Values will be copied.
 
template<CBooleanTestable = T>
bool BecameTrue (bool fallback=false) const
 Returns true when this state is currently true, but previously it wasn't.
 
template<CBooleanTestable = T>
bool OnDown (bool fallback=false) const
 Returns true when this state is currently true, but previously it wasn't.
 
template<CBooleanTestable = T>
bool BecameFalse (bool fallback=false) const
 Returns true when this state is currently false, but previously it wasn't.
 
template<CBooleanTestable = T>
bool OnUp (bool fallback=false) const
 Returns true when this state is currently false, but previously it wasn't.
 
template<CCoreEqualityComparable = T>
bool HasChanged () const
 Returns true when current value is not equal to previous one.
 
template<CCoreEqualityComparable = T>
bool HasChanged (T const &fallback) const
 Returns true when current value is not equal to previous one.
 
template<typename Self >
 operator T const & (this Self &&self)
 
template<typename Self >
const T * operator-> (this Self &&self)
 

Data Fields

FStatePolicy PolicyFlags { DefaultPolicy }
 

Static Public Attributes

static constexpr FStatePolicy DefaultPolicyFlags = DefaultPolicy
 

Protected Member Functions

virtual FDelegateHandle OnChangeImpl (TDelegate< void(TChangeData< T > const &)> &&onChange, FEventPolicy const &eventPolicy={}) override
 
- Protected Member Functions inherited from Mcro::Observable::IState< T >

Additional Inherited Members

- Static Protected Member Functions inherited from Mcro::Observable::IState< T >
template<CChangeListener< T > Function>
static auto DelegateValueArgument (Function const &onChange)
 

Detailed Description

template<typename T, FStatePolicy DefaultPolicy>
struct Mcro::Observable::TState< T, DefaultPolicy >

Storage wrapper for any value which state needs to be tracked or their change needs to be observed. By default, TState is not thread-safe unless FStatePolicy::ThreadSafe policy is active in DefaultPolicy.

TState and IState allows developers an expressive API for tracking/syncing changes of a stateful entity. Like button presses, resolution changes or storing the last error. It doesn't only give a storage for the value but triggers events when the value changes. This alleviates the need for explicit OnStuffChanged events in the API where TState is used.

Use TState on class members where a default set of policy can be declared in compile time, and use IState where these states should be referenced in a function argument for example. In the latter case the policy flags are erased so multiple states with different policies are compatible with each-other. Although that is not necessary and not recommended if we would only need to consume their value, as states can have implicit conversion to their value (returning a const-ref).

If given value is equality comparable, TState will only trigger change events when the previous and the current values are different. Unless that behavior is overridden by FStatePolicy flags. A default set of flags are determined by StatePolicyFor template for any given type.

Definition at line 367 of file Observable.h.

Member Typedef Documentation

◆ ReadLockType

template<typename T , FStatePolicy DefaultPolicy>
using Mcro::Observable::TState< T, DefaultPolicy >::ReadLockType = ThreadSafeSwitch<FReadScopeLock, FVoid>

Definition at line 377 of file Observable.h.

◆ ReadLockVariant

template<typename T , FStatePolicy DefaultPolicy>
using Mcro::Observable::IState< T >::ReadLockVariant

Definition at line 60 of file Observable.h.

◆ StateBase

template<typename T , FStatePolicy DefaultPolicy>
using Mcro::Observable::TState< T, DefaultPolicy >::StateBase = IState<T>

Definition at line 372 of file Observable.h.

◆ ThreadSafeSwitch

template<typename T , FStatePolicy DefaultPolicy>
template<typename ThreadSafeType , typename NaiveType >
using Mcro::Observable::TState< T, DefaultPolicy >::ThreadSafeSwitch = std::conditional_t<DefaultPolicy.ThreadSafe, ThreadSafeType, NaiveType>

Definition at line 370 of file Observable.h.

◆ WriteLockType

template<typename T , FStatePolicy DefaultPolicy>
using Mcro::Observable::TState< T, DefaultPolicy >::WriteLockType = ThreadSafeSwitch<FWriteScopeLock, FVoid>

Definition at line 378 of file Observable.h.

◆ WriteLockVariant

template<typename T , FStatePolicy DefaultPolicy>
using Mcro::Observable::IState< T >::WriteLockVariant

Definition at line 61 of file Observable.h.

Constructor & Destructor Documentation

◆ TState() [1/7]

template<typename T , FStatePolicy DefaultPolicy>
template<CDefaultInitializable = T>
Mcro::Observable::TState< T, DefaultPolicy >::TState ( )
inline

Enable default constructor only when T is default initializable.

Definition at line 384 of file Observable.h.

◆ TState() [2/7]

template<typename T , FStatePolicy DefaultPolicy>
template<CCopyConstructible = T>
Mcro::Observable::TState< T, DefaultPolicy >::TState ( T const & value)
inlineexplicit

Enable copy constructor for T only when T is copy constructable.

Definition at line 388 of file Observable.h.

◆ TState() [3/7]

template<typename T , FStatePolicy DefaultPolicy>
template<CMoveConstructible = T>
Mcro::Observable::TState< T, DefaultPolicy >::TState ( T && value)
inlineexplicit

Enable move constructor for T only when T is move constructable.

Definition at line 392 of file Observable.h.

◆ TState() [4/7]

template<typename T , FStatePolicy DefaultPolicy>
template<CCopyConstructible = T>
Mcro::Observable::TState< T, DefaultPolicy >::TState ( TState< T, DefaultPolicy > const & other)
inline

Enable copy constructor for the state only when T is copy constructable.

Definition at line 396 of file Observable.h.

◆ TState() [5/7]

template<typename T , FStatePolicy DefaultPolicy>
template<CMoveConstructible = T>
Mcro::Observable::TState< T, DefaultPolicy >::TState ( TState< T, DefaultPolicy > && other)
inline

Enable move constructor for the state only when T is move constructable.

Definition at line 400 of file Observable.h.

◆ TState() [6/7]

template<typename T , FStatePolicy DefaultPolicy>
template<typename Arg >
requires (!CConvertibleTo<Arg, TState> && !CSameAs<Arg, T>)
Mcro::Observable::TState< T, DefaultPolicy >::TState ( Arg && arg)
inline

Construct value in-place with non-semantic single argument constructor.

Definition at line 405 of file Observable.h.

◆ TState() [7/7]

template<typename T , FStatePolicy DefaultPolicy>
template<typename... Args>
requires (sizeof...(Args) > 1)
Mcro::Observable::TState< T, DefaultPolicy >::TState ( Args &&... args)
inline

Construct value in-place with multiple argument constructor.

Definition at line 410 of file Observable.h.

Member Function Documentation

◆ Get()

template<typename T , FStatePolicy DefaultPolicy>
virtual T const & Mcro::Observable::TState< T, DefaultPolicy >::Get ( ) const
inlineoverridevirtual

Get the wrapped value if for some reason the conversion operator is not enough or deleted. Thread safety is not considered in this function, use ReadLock before Get, or use GetOnAnyThread which provides a read lock, if thread safety is a concern.

Implements Mcro::Observable::IState< T >.

Definition at line 412 of file Observable.h.

◆ GetOnAnyThread()

template<typename T , FStatePolicy DefaultPolicy>
virtual TTuple< T const &, TUniquePtr< ReadLockVariant > > Mcro::Observable::TState< T, DefaultPolicy >::GetOnAnyThread ( ) const
inlineoverridevirtual

If thread safety is enabled in DefaultPolicy, get the value with a bundled read-scope-lock. Otherwise the tuple returns an empty dummy struct as its second argument.

Use C++17 structured binding for convenience:

auto [value, lock] = MyState.GetOnAnyThread();
Remarks
Unlike the placeholder auto keyword, the structured binding auto keyword preserves reference qualifiers. See https://godbolt.org/z/jn918fKfd
Returns
The lock is returned as TUniquePtr it's slightly more expensive because of ref-counting but it makes the API so much easier to use as TState can decide to return a real lock or just a dummy.

Implements Mcro::Observable::IState< T >.

Definition at line 414 of file Observable.h.

◆ GetPrevious() [1/2]

template<typename T , FStatePolicy DefaultPolicy>
virtual TOptional< T > const & Mcro::Observable::TState< T, DefaultPolicy >::GetPrevious ( ) const
inlineoverridevirtual

Get the previous value if StorePrevious is enabled and there was at least one change.

Implements Mcro::Observable::IState< T >.

Definition at line 522 of file Observable.h.

◆ GetPrevious() [2/2]

template<typename T , FStatePolicy DefaultPolicy>
virtual T const & Mcro::Observable::TState< T, DefaultPolicy >::GetPrevious ( T const & fallback) const
inlineoverridevirtual

Get the previous value if StorePrevious is enabled and there was at least one change. Get a fallback value otherwise.

Parameters
fallbackReturn this value if there's no previous one available

Implements Mcro::Observable::IState< T >.

Definition at line 527 of file Observable.h.

◆ GetPreviousOrCurrent()

template<typename T , FStatePolicy DefaultPolicy>
virtual T const & Mcro::Observable::TState< T, DefaultPolicy >::GetPreviousOrCurrent ( ) const
inlineoverridevirtual

Get the previous value if StorePrevious is enabled and there was at least one change or the current value otherwise.

Implements Mcro::Observable::IState< T >.

Definition at line 532 of file Observable.h.

◆ HasChangedFrom()

template<typename T , FStatePolicy DefaultPolicy>
virtual bool Mcro::Observable::TState< T, DefaultPolicy >::HasChangedFrom ( const T & nextValue)
inlineoverridevirtual

Given value will be stored in the state only if T is equality comparable and it differs from the current state value. If T is not equality comparable this function is equivalent to Set and always returns true.

Returns
True if the given value was different from the previous state value. Always returns true when T is is not equality comparable.

Implements Mcro::Observable::IState< T >.

Definition at line 492 of file Observable.h.

◆ HasEverChanged()

template<typename T , FStatePolicy DefaultPolicy>
virtual bool Mcro::Observable::TState< T, DefaultPolicy >::HasEverChanged ( ) const
inlineoverridevirtual

Returns true if this state has ever been changed from its initial value given at construction.

Implements Mcro::Observable::IState< T >.

Definition at line 507 of file Observable.h.

◆ Modify()

template<typename T , FStatePolicy DefaultPolicy>
virtual void Mcro::Observable::TState< T, DefaultPolicy >::Modify ( TUniqueFunction< void(T &)> && modifier,
bool alwaysNotify = true )
inlineoverridevirtual

Modify this state via an l-value ref in a functor.

Parameters
modifierThe functor which modifies this value
alwaysNotifyNotify observers about the change even when the previous state is not different after the modification. This is only applicable when T is copyable, comparable, StorePrevious flag is set and AlwaysNotify flag is not set via policy.

Implements Mcro::Observable::IState< T >.

Definition at line 442 of file Observable.h.

◆ NormalizePrevious()

template<typename T , FStatePolicy DefaultPolicy>
virtual void Mcro::Observable::TState< T, DefaultPolicy >::NormalizePrevious ( )
inlineoverridevirtual

Set the previous value to the current one. Useful in Ticks.

It will not trigger change notifications but it will use a write-lock when thread-safety is enabled. If StorePrevious is disabled it will do nothing.

Implements Mcro::Observable::IState< T >.

Definition at line 537 of file Observable.h.

◆ OnChangeImpl()

template<typename T , FStatePolicy DefaultPolicy>
virtual FDelegateHandle Mcro::Observable::TState< T, DefaultPolicy >::OnChangeImpl ( TDelegate< void(TChangeData< T > const &)> && onChange,
FEventPolicy const & eventPolicy = {} )
inlineoverrideprotectedvirtual

Implements Mcro::Observable::IState< T >.

Definition at line 473 of file Observable.h.

◆ operator=()

template<typename T , FStatePolicy DefaultPolicy>
template<CConvertibleTo< T > Other>
requires (!CState<Other>)
TState & Mcro::Observable::TState< T, DefaultPolicy >::operator= ( Other && value)
inline

Definition at line 550 of file Observable.h.

◆ ReadLock()

template<typename T , FStatePolicy DefaultPolicy>
virtual TUniquePtr< ReadLockVariant > Mcro::Observable::TState< T, DefaultPolicy >::ReadLock ( ) const
inlineoverridevirtual

Lock this state for reading for the current scope.

Returns
The lock is returned as TUniquePtr it's slightly more expensive because of ref-counting but it makes the API so much easier to use as TState can decide to return a real lock or just a dummy.

Implements Mcro::Observable::IState< T >.

Definition at line 512 of file Observable.h.

◆ Remove()

template<typename T , FStatePolicy DefaultPolicy>
virtual bool Mcro::Observable::TState< T, DefaultPolicy >::Remove ( FDelegateHandle const & handle)
inlineoverridevirtual

Equivalent to TMulticastDelegate::Remove

Implements Mcro::Observable::IState< T >.

Definition at line 480 of file Observable.h.

◆ RemoveAll()

template<typename T , FStatePolicy DefaultPolicy>
virtual int32 Mcro::Observable::TState< T, DefaultPolicy >::RemoveAll ( const void * object)
inlineoverridevirtual

Equivalent to TMulticastDelegate::RemoveAll

Implements Mcro::Observable::IState< T >.

Definition at line 486 of file Observable.h.

◆ Set()

template<typename T , FStatePolicy DefaultPolicy>
virtual void Mcro::Observable::TState< T, DefaultPolicy >::Set ( T const & value)
inlineoverridevirtual

Set the wrapped value if for some reason the assignment operator is not enough or deleted. When thread safety is enabled Set will automatically lock this state for writing.

Warning
Setting this state from within its change listeners is prohibited and will trigger a check()

Implements Mcro::Observable::IState< T >.

Definition at line 419 of file Observable.h.

◆ WriteLock()

template<typename T , FStatePolicy DefaultPolicy>
virtual TUniquePtr< WriteLockVariant > Mcro::Observable::TState< T, DefaultPolicy >::WriteLock ( )
inlineoverridevirtual

Lock this state for writing for the current scope.

Returns
The lock is returned as TUniquePtr it's slightly more expensive because of ref-counting but it makes the API so much easier to use as TState can decide to return a real lock or just a dummy.

Implements Mcro::Observable::IState< T >.

Definition at line 517 of file Observable.h.

Field Documentation

◆ DefaultPolicyFlags

template<typename T , FStatePolicy DefaultPolicy>
FStatePolicy Mcro::Observable::TState< T, DefaultPolicy >::DefaultPolicyFlags = DefaultPolicy
staticconstexpr

Definition at line 380 of file Observable.h.

◆ PolicyFlags

template<typename T , FStatePolicy DefaultPolicy>
FStatePolicy Mcro::Observable::TState< T, DefaultPolicy >::PolicyFlags { DefaultPolicy }

Definition at line 559 of file Observable.h.


The documentation for this struct was generated from the following files: