-
Notifications
You must be signed in to change notification settings - Fork 130
Domain.h
#include "react/Domain.h"
Contains the base class for reactive domains and the macro to define them.
This class contains the functionality for domains defined with REACTIVE_DOMAIN
.
A domain cannot be instantiated. It is used to group domain-specific type aliases and static functions.
namespace react
{
template <typename D>
class DomainBase
{
public:
DomainBase() = delete;
// Type aliases for this domain
template <typename S>
using SignalT = Signal<D,S>;
template <typename S>
using VarSignalT = VarSignal<D,S>;
template <typename E = Token>
using EventsT = Events<D,E>;
template <typename E = Token>
using EventSourceT = EventSource<D,E>;
using ObserverT = Observer<D>;
using ReactorT = Reactor<D>;
// Run given function in transaction mode
static void DoTransaction(F&& func);
static void DoTransaction(TurnFlagsT flags, F&& func);
};
}
DomainBase() = delete;
Deleted default constructor to prevent instantiation.
template <typename F>
static void DoTransaction(F&& func); // (1)
template <typename F>
static void DoTransaction(TurnFlagsT flags, F&& func); // (2)
Runs func
in transaction mode. During transaction mode, all reactive inputs are collected and propagated in a single turn after func
returns.
The purpose of this is
- to ensure consistency, if there exist certain invariants between reactive inputs;
- to avoid redundant re-calculations;
- to avoid the overhead of additional turns.
(1) uses the default turn flags for the transaction. (2) allows to set flags explicitly.
This class manages ownership of a continuation. A continuation is a link between two domains (including from a domain to itself).
namespace react
{
template
<
typename D,
typename D2
>
class Continuation
{
// Type aliases
using SourceDomainT = D;
using TargetDomainT = D2;
// Constructor
Continuation();
Continuation(Continuation&& other);
// Assignemnt
Continuation& operator=(Continuation&& other);
};
}
D | The domain this continuation belongs to. Aliased as member type SourceDomainT . |
D2 | Signal value type. Aliased as member type TargetDomainT . |
namespace react
{
// Creates a continuation from domain D to D2
Continuation<D,D2>
MakeContinuation<D,D2>(const Signal<D,S>& trigger, F&& func);
Continuation<D,D2>
MakeContinuation<D,D2>(const Events<D,E>& trigger, F&& func);
Continuation<D,D2>
MakeContinuation<D,D2>(const Events<D,E>& trigger,
const SignalPack<D,TDepValues...>& depPack, F&& func);
}
// (1)
template
<
typename D,
typename D2 = D,
typename S,
typename FIn
>
Continuation<D,D2> MakeContinuation(const Signal<D,S>& trigger, FIn&& func);
// (2)
template
<
typename D,
typename D2 = D,
typename E,
typename FIn
>
Continuation<D,D2> MakeContinuation(const Events<D,E>& trigger, FIn&& func);
// (3)
template
<
typename D,
typename D2 = D,
typename E,
typename FIn,
typename ... TDepValues
>
Continuation<D,D2>
MakeContinuation(const Events<D,E>& trigger,
const SignalPack<D,TDepValues...>& depPack, FIn&& func);
(1) When the signal value s
of trigger
changes, func(s)
is executed in a transaction of domain D2
.
In pseudo code:
D2::DoTransaction([func, s] {
func(s)
});
(2) For every event e
in trigger
, func(e)
is called in a transaction of domain D2
.
Multiple events from the same turn are captured in a single transaction.
In pseudo code:
D2::DoTransaction([func, events] {
for (const auto& e : events)
func(e);
});
(3) Similar to (2), but the synchronized values of signals in depPack
are passed to func
as additional arguments.
Changes of signals in depPack
do not trigger an update - only received events do.
In pseudo code:
D2::DoTransaction([func, events, depValues...] {
for (const auto& e : events)
func(e, depValues ...);
});
The signature of func
should be equivalent to:
- (1)
void func(const S&)
- (2)
void func(const E&)
- (3)
void func(const E&, const TDepValues& ...)
D2::DoTransaction([func, events, depValues...] {
for (const auto& e : events)
func(e, depValues ...);
});
REACTIVE_DOMAIN(name, ...)
Defines a reactive domain name
, declared as class name : public DomainBase<name>
. Also initializes static data for this domain.
The optional parameter is the propagation engine. If omitted, Toposort<sequential>
is used as default.
USING_REACTIVE_DOMAIN(name)
Defines the following type aliases for the given domain name in the current scope:
template <typename S>
using SignalT = Signal<name,S>;
template <typename S>
using VarSignalT = VarSignal<name,S>;
template <typename E = Token>
using EventsT = Events<name,E>;
template <typename E = Token>
using EventSourceT = EventSource<name,E>;
using ObserverT = Observer<name>;
using ReactorT = Reactor<name>;