// Copyright Sebastian Jeckel 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include
#include
#include
#include
#include "react/Domain.h"
#include "react/Signal.h"
#include "react/Event.h"
#include "react/Observer.h"
#include "react/Algorithm.h"
///////////////////////////////////////////////////////////////////////////////////////////////////
/// Example 1 - Converting events to signals
///////////////////////////////////////////////////////////////////////////////////////////////////
namespace example1
{
using namespace std;
using namespace react;
REACTIVE_DOMAIN(D, sequential)
class Sensor
{
public:
USING_REACTIVE_DOMAIN(D)
EventSourceT Samples = MakeEventSource();
SignalT LastSample = Hold(Samples, 0);
};
void Run()
{
cout << "Example 1 - Converting events to signals" << endl;
Sensor mySensor;
Observe(mySensor.LastSample, [] (int v) {
std::cout << v << std::endl;
});
mySensor.Samples << 20 << 21 << 21 << 22; // output: 20, 21, 22
DoTransaction([&] {
mySensor.Samples << 30 << 31 << 31 << 32;
}); // output: 32
cout << endl;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/// Example 2 - Converting signals to events
///////////////////////////////////////////////////////////////////////////////////////////////////
namespace example2
{
using namespace std;
using namespace react;
REACTIVE_DOMAIN(D, sequential)
class Employee
{
public:
USING_REACTIVE_DOMAIN(D)
VarSignalT Name = MakeVar(string( "Bob" ));
VarSignalT Salary = MakeVar(3000);
EventsT SalaryChanged = Monitor(Salary);
};
void Run()
{
cout << "Example 2 - Converting signals to events" << endl;
Employee bob;
Observe(
bob.SalaryChanged,
With(bob.Name),
[] (int newSalary, const string& name) {
cout << name << " now earns " << newSalary << endl;
});
cout << endl;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/// Example 3 - Folding event streams into signals (1)
///////////////////////////////////////////////////////////////////////////////////////////////////
namespace example3
{
using namespace std;
using namespace react;
REACTIVE_DOMAIN(D, sequential)
class Counter
{
public:
USING_REACTIVE_DOMAIN(D)
EventSourceT<> Increment = MakeEventSource();
SignalT Count = Iterate(
Increment,
0,
[] (Token, int oldCount) {
return oldCount + 1;
});
};
void Run()
{
cout << "Example 3 - Folding event streams into signals (1)" << endl;
Counter myCounter;
// Note: Using function-style operator() instead of .Emit() and .Value()
myCounter.Increment();
myCounter.Increment();
myCounter.Increment();
cout << myCounter.Count() << endl; // output: 3
cout << endl;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/// Example 4 - Folding event streams into signals (2)
///////////////////////////////////////////////////////////////////////////////////////////////////
namespace example4
{
using namespace std;
using namespace react;
REACTIVE_DOMAIN(D, sequential)
class Sensor
{
public:
USING_REACTIVE_DOMAIN(D)
EventSourceT Input = MakeEventSource();
SignalT Count = Iterate(
Tokenize(Input),
0,
[] (Token, int oldCount) {
return oldCount + 1;
});
SignalT Sum = Iterate(
Input,
0.0f,
[] (float v, float sum) {
return v + sum;
});
SignalT Average = MakeSignal(
With(Sum,Count),
[] (float sum, int count) {
return count != 0 ? sum / count : 0.0f;
});
};
void Run()
{
cout << "Example 4 - Folding event streams into signals (2)" << endl;
Sensor mySensor;
mySensor.Input << 10.0f << 5.0f << 10.0f << 8.0f;
cout << "Average: " << mySensor.Average() << endl; // output: 8.25
cout << endl;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/// Example 5 - Folding event streams into signals (3)
///////////////////////////////////////////////////////////////////////////////////////////////////
namespace example5
{
using namespace std;
using namespace react;
REACTIVE_DOMAIN(D, sequential)
enum ECmd { increment, decrement, reset };
class Counter
{
public:
USING_REACTIVE_DOMAIN(D)
EventSourceT Update = MakeEventSource();
VarSignalT Delta = MakeVar(1);
VarSignalT Start = MakeVar(0);
SignalT Count = Iterate(
Update,
Start.Value(),
With(Delta, Start),
[] (int cmd, int oldCount, int delta, int start) {
if (cmd == increment)
return oldCount + delta;
else if (cmd == decrement)
return oldCount - delta;
else
return start;
});
};
void Run()
{
cout << "Example 5 - Folding event streams into signals (3)" << endl;
Counter myCounter;
cout << "Start: " << myCounter.Count() << endl; // output: 0
myCounter.Update(increment);
myCounter.Update(increment);
myCounter.Update(increment);
cout << "3x increment by 1: " << myCounter.Count() << endl; // output: 3
myCounter.Delta <<= 5;
myCounter.Update(decrement);
cout << "1x decrement by 5: " << myCounter.Count() << endl; // output: -2
myCounter.Start <<= 100;
myCounter.Update(reset);
cout << "reset to 100: " << myCounter.Count() << endl; // output: 100
cout << endl;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/// Example 6 - Avoiding expensive copies
///////////////////////////////////////////////////////////////////////////////////////////////////
namespace example6
{
using namespace std;
using namespace react;
REACTIVE_DOMAIN(D, sequential)
class Sensor
{
public:
USING_REACTIVE_DOMAIN(D)
EventSourceT Input = MakeEventSource();
VarSignalT Threshold = MakeVar(42);
SignalT> AllSamples = Iterate(
Input,
vector{},
[] (int input, vector& all) {
all.push_back(input);
});
SignalT> CriticalSamples = Iterate(
Input,
vector{},
With(Threshold),
[] (int input, vector& critical, int threshold) {
if (input > threshold)
critical.push_back(input);
});
};
void Run()
{
cout << "Example 6 - Avoiding expensive copies" << endl;
Sensor mySensor;
mySensor.Input << 40 << 29 << 43 << 50;
cout << "All samples: ";
for (auto const& v : mySensor.AllSamples())
cout << v << " ";
cout << endl;
cout << "Critical samples: ";
for (auto const& v : mySensor.CriticalSamples())
cout << v << " ";
cout << endl;
cout << endl;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/// Run examples
///////////////////////////////////////////////////////////////////////////////////////////////////
int main()
{
example1::Run();
example2::Run();
example3::Run();
example4::Run();
example5::Run();
example6::Run();
return 0;
}