Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

youngkan/cpp.react

Open more actions menu
 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

199 Commits
199 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Introduction

Cpp.React is an experimental Reactive Programming framework for C++11. Its purpose is to provide abstractions that simplify the implementation of reactive behaviour.

The general idea is that dependency relations between data/actions are expressed declarively, while the actual propagation of changes is handled automatically. The benefits:

  • Reduction of boilerplate code.
  • Updating is always consistent and glitch-free.
  • Support for implicit parallelization of updates.

Compiling

I mainly tested the build on Windows with Visual Studio 2013. The Intel C++ Compiler 14.0 with Visual Studio 2012/13 is theoretically supported as well, but it doesn't compile the current codebase anymore due to some bugs with C++11 support.

Cpp.React uses standard C++11 and the dependencies are portable, so other compilers/platforms should work, too.

Dependencies

Features by example

Signals

Signals are time-varying reactive values, that can be combined to create reactive expressions. These expressions are automatically recalculated whenever one of their dependent values changes.

#include "react/Signal.h"
///...
using namespace react;

REACTIVE_DOMAIN(MyDomain);

auto width  = MyDomain::MakeVar(1);
auto height = MyDomain::MakeVar(2);

auto area   = width * height;

cout << "area: " << area() << endl; // => area: 2
width <<= 10;
cout << "area: " << area() << endl; // => area: 20

For more information, see the Signal guide

Event streams

Event streams represent flows of discrete values as first-class objects, based on ideas found in Deprecating the Observer Pattern.

#include "react/EventStream.h"
//...
using namespace react;

REACTIVE_DOMAIN(MyDomain);

auto leftClicked  = MyDomain::MakeEventSource();
auto rightClicked = MyDomain::MakeEventSource();

auto clicked = leftClicked | rightClicked;

Observe(clicked, [] { cout << "button clicked!" << endl; });

Implicit parallelism

The change propagation is handled implicitly by a so called propagation engine. Depending on the selected engine, independent propagation paths are automatically parallelized. For more details, see Propagation Engines.

#include "react/propagation/TopoSortEngine.h"
//...
using namespace react;

// Single-threaded updating
REACTIVE_DOMAIN(MyDomain, TopoSortEngine<sequential>);

// Parallel updating
REACTIVE_DOMAIN(MyDomain, TopoSortEngine<parallel>);

// Input from multiple threads
REACTIVE_DOMAIN(MyDomain, TopoSortEngine<sequential_queuing>);
REACTIVE_DOMAIN(MyDomain, TopoSortEngine<parallel_queuing>);

// Parallel updating + input from multiple threads + pipelining
REACTIVE_DOMAIN(MyDomain, TopoSortEngine<parallel_pipelining>);

Reactive loops

#include "react/Reactor.h"
//...
using namespace react;

REACTIVE_DOMAIN(D);

using PointT = pair<int,int>;
using PathT  = vector<PointT>;

vector<PathT> paths;

auto mouseDown = D::MakeEventSource<PointT>();
auto mouseUp   = D::MakeEventSource<PointT>();
auto mouseMove = D::MakeEventSource<PointT>();

D::ReactiveLoopT loop
{
	[&] (D::ReactiveLoopT::Context& ctx)
	{
		PathT points;

		points.emplace_back(ctx.Await(mouseDown));

		ctx.RepeatUntil(mouseUp, [&] {
			points.emplace_back(ctx.Await(mouseMove));
		});

		points.emplace_back(ctx.Await(mouseUp));

		paths.push_back(points);
	}
};

mouseDown << PointT(1,1);
mouseMove << PointT(2,2) << PointT(3,3) << PointT(4,4);
mouseUp   << PointT(5,5);

mouseMove << PointT(999,999);

mouseDown << PointT(10,10);
mouseMove << PointT(20,20);
mouseUp   << PointT(30,30);

// => paths[0]: (1,1) (2,2) (3,3) (4,4) (5,5)
// => paths[1]: (10,10) (20,20) (30,30)

Reactive objects and dynamic reactives

#include "react/ReactiveObject.h"
//...
REACTIVE_DOMAIN(D);

using namespace react;

class Company : public ReactiveObject<D>
{
public:
    VarSignalT<string>    Name;

    Company(const char* name) :
        Name{ MakeVar(string(name)) }
    {
    }

    inline bool operator==(const Company& other) const { /* ... */ }
};

class Manager : public ReactiveObject<D>
{
    ObserverT nameObs;

public:
    VarRefSignalT<Company>    CurrentCompany;

    Manager(initialCompany& company) :
        CurrentCompany{ MakeVar(std::ref(company)) }
    {
        nameObs = REACTIVE_REF(CurrentCompany, Name).Observe([] (string name) {
            cout << "Manager: Now managing " << name << endl;
        });
    }
};

More examples

About

C++React: A reactive programming library for C++11.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C++ 99.7%
  • CMake 0.3%
Morty Proxy This is a proxified and sanitized view of the page, visit original site.