// 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 "react/Domain.h"
#include "react/Event.h"
#include "react/Observer.h"
///////////////////////////////////////////////////////////////////////////////////////////////////
/// Example 1 - Hello world
///////////////////////////////////////////////////////////////////////////////////////////////////
namespace example1
{
using namespace std;
using namespace react;
// Defines a domain.
// Each domain represents a separate dependency graph, managed by a dedicated propagation engine.
// Reactives of different domains can not be combined.
REACTIVE_DOMAIN(D, sequential)
// Define type aliases for the given domain in this namespace.
// Now we can use EventSourceT instead of D::EventSourceT.
USING_REACTIVE_DOMAIN(D)
// An event source that emits values of type string
namespace v1
{
EventSourceT mySource = MakeEventSource();
void Run()
{
cout << "Example 1 - Hello world (string source)" << endl;
Observe(mySource, [] (const string& s) {
std::cout << s << std::endl;
});
mySource << string("Hello world #1");
// Or without the operator:
mySource.Emit(string("Hello world #2"));
// Or as a function call:
mySource(string("Hello world #3"));
cout << endl;
}
}
// An event source without an explicit value type
namespace v2
{
EventSourceT<> helloWorldTrigger = MakeEventSource();
void Run()
{
cout << "Example 1 - Hello world (token source)" << endl;
int count = 0;
Observe(helloWorldTrigger, [&] (Token) {
cout << "Hello world #" << ++count << endl;
});
helloWorldTrigger.Emit();
// Or without the stream operator:
helloWorldTrigger << Token::value;
// Or as a function call:
helloWorldTrigger();
cout << endl;
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/// Example 2 - Merging event streams
///////////////////////////////////////////////////////////////////////////////////////////////////
namespace example2
{
using namespace std;
using namespace react;
REACTIVE_DOMAIN(D, sequential)
USING_REACTIVE_DOMAIN(D)
// An event stream that merges both sources
namespace v1
{
EventSourceT<> leftClick = MakeEventSource();
EventSourceT<> rightClick = MakeEventSource();
EventsT<> anyClick = Merge(leftClick, rightClick);
void Run()
{
cout << "Example 2 - Merging event streams (Merge)" << endl;
int count = 0;
Observe(anyClick, [&] (Token) {
cout << "clicked #" << ++count << endl;
});
leftClick.Emit(); // output: clicked #1
rightClick.Emit(); // output: clicked #2
cout << endl;
}
}
// Using overloaded operator | instead of explicit Merge
namespace v2
{
EventSourceT<> leftClick = MakeEventSource();
EventSourceT<> rightClick = MakeEventSource();
EventsT<> anyClick = leftClick | rightClick;
void Run()
{
cout << "Example 2 - Merging event streams (operator)" << endl;
int count = 0;
Observe(anyClick, [&] (Token) {
cout << "clicked #" << ++count << endl;
});
leftClick.Emit(); // output: clicked #1
rightClick.Emit(); // output: clicked #2
cout << endl;
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/// Example 3 - Filtering events
///////////////////////////////////////////////////////////////////////////////////////////////////
namespace example3
{
using namespace std;
using namespace react;
REACTIVE_DOMAIN(D, sequential)
USING_REACTIVE_DOMAIN(D)
EventSourceT numbers = MakeEventSource();
EventsT greater10 = Filter(numbers, [] (int n) {
return n > 10;
});
void Run()
{
cout << "Example 3 - Filtering events" << endl;
Observe(greater10, [] (int n) {
cout << n << endl;
});
numbers << 5 << 11 << 7 << 100; // output: 11, 100
cout << endl;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/// Example 4 - Filtering events
///////////////////////////////////////////////////////////////////////////////////////////////////
namespace example4
{
using namespace std;
using namespace react;
REACTIVE_DOMAIN(D, sequential)
USING_REACTIVE_DOMAIN(D)
// Data types
enum class ETag { normal, critical };
using TaggedNum = pair;
EventSourceT numbers = MakeEventSource();
EventsT tagged = Transform(numbers, [] (int n) {
if (n > 10)
return TaggedNum( ETag::critical, n );
else
return TaggedNum( ETag::normal, n );
});
void Run()
{
cout << "Example 4 - Transforming events" << endl;
Observe(tagged, [] (const TaggedNum& t) {
if (t.first == ETag::critical)
cout << "(critical) " << t.second << endl;
else
cout << "(normal) " << t.second << endl;
});
numbers << 5; // output: (normal) 5
numbers << 20; // output: (critical) 20
cout << endl;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/// Example 5 - Queuing multiple inputs
///////////////////////////////////////////////////////////////////////////////////////////////////
namespace example5
{
using namespace std;
using namespace react;
REACTIVE_DOMAIN(D, sequential)
USING_REACTIVE_DOMAIN(D)
EventSourceT src = MakeEventSource();
void Run()
{
cout << "Example 5 - Queuing multiple inputs" << endl;
Observe(src, [] (int v) {
cout << v << endl;
}); // output: 1, 2, 3, 4
DoTransaction([] {
src << 1 << 2 << 3;
src << 4;
});
cout << endl;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/// Run examples
///////////////////////////////////////////////////////////////////////////////////////////////////
int main()
{
example1::v1::Run();
example1::v2::Run();
example2::v1::Run();
example2::v2::Run();
example3::Run();
example4::Run();
example5::Run();
return 0;
}