Skip to content

Implementation of async observable/observer (Reactive Programming) in C++ with care about performance and templates in mind in ReactiveX approach

License

Notifications You must be signed in to change notification settings

victimsnino/ReactivePlusPlus

Repository files navigation

ReactivePlusPlus

CI v2 codecov Lines of Code Maintainability Rating GitHub commit activity (v2)

User guide API Reference Benchmarks

Join the chat in Discord: https://discord.gg/KWMR3RNkVz Conan Center Vcpkg Version

What is that?

ReactivePlusPlus is reactive programming library for C++20 language inspired by "official implementation" (RxCpp) and original idea (ReactiveX) that only depends on standard library and C++20 features (mostly on concepts).

But... what is that?

To put it even simpler: ReactivePlusPlus is library for building asynchronous event-driven streams of data with help of sequences of primitive operators in the declarative form. Like this:

rpp::source::from_callable(&::getchar)
   | rpp::operators::repeat()
   | rpp::operators::take_while([](char v) { return v != '0'; })
   | rpp::operators::filter(std::not_fn(&::isdigit))
   | rpp::operators::map(&::toupper)
   | rpp::operators::subscribe([](char v) { std::cout << v; });

Try it on godbolt!

Explanation There we are creating observable (soure of emissions/values/data) to emit value via invoking of `getchar` function, `repeat`-ing it infinite amount of time till termination event happening. It emits values while symbol is not equal to `0`, taking only **not** digits, maping them to upper case and then just printing to console.

Also RPP supports out of box:

What about existing Reactive Extension libraries for C++?

Reactive programming is a powerful paradigm for creating multi-threaded and real-time applications. Unfortunately, at the moment of creating ReactivePlusPlus, there is only one stable and fully-implemented library available - RxCpp.

While RxCpp is a great and powerful library, it has some disadvantages. It is written in C++11 and contains parts written in pre-C++11 style. This leads to a mess of old-style classes and wrappers. Additionally, the rxcpp::observable type has a long chain of template parameters, which can lead to slower IDE performance and larger binaries. Sometimes it has bad performance due to tremendous amount of usage of heap or just non-effective logic.

Another implementation, another-rxcpp, uses type erasure and std::function, but this approach results in larger observer/observable sizes and potentially causes performance issues.

Why ReactivePlusPlus?

ReactivePlusPlus tries to solve all mentioned issues:

  • ReactivePlusPlus written in Modern C++ (C++20) with concepts which makes code-base a lot more understandable and clean:
    • Concepts provide more clear errors and checks: you will understand that pass something incorrect before compilation in IDE or during compilation with understandable errors instead of "invalid template class map_invalid_t"
    • Everywhere while possible used deduction of template arguments, for example, type of values of observable by type of subscriber used in on_subscribe and etc
  • ReactivePlusPlus keeps balance between performance and type-erasing mechanism
  • ReactivePlusPlus is fast: every part of code written with performance in mind. Starting from tests over amount of copies/move and finishing to Continuous Benchmarking. Benchmarks prove that RPP faster than RxCPP in most cases: Continuous benchmarking results and comparison with RxCpp

Currently ReactivePlusPlus is still under development but it has a lot of implemented operators for now. List of implemented features can be found in API Reference with very detailed documentation for each of them.

Main advantages of ReactivePlusPlus are that it is written in Modern C++ with Performance and Usage in mind. v2 is written to follow the "zero-overhead principle". As a result, it is fast, readable, easy to use, and well-documented. This is proven by continuous benchmarking results of v2 and comparison with RxCpp.

Usage

See the BUILDING document to know how to build/install RPP. If you are going to know more details about developing for RPP check HACKING document.

Important

ReactivePlusPlus is library for C++20. So, it works only on compilers that supports most C++20 features. List of minimal supported compilers:

  • (ubuntu) gcc-10
  • (ubuntu) clang-11
  • (windows) visual studio 2022
  • (macos) Apple Clang 14

Documentation:

Check detailed User Guide/Tutorial (to learn more details about ReactivePlusPlus or reactive programming paradigm itself) and extensive API Reference of RPP (to know how to apply ReactivePlusPlus properly).

Useful links

Licensing

Boost Software License - Version 1.0 - August 17th, 2003

Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:

The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

Credits:

ReactivePlusPlus library uses:

  • PVS-Studio - static analyzer for C, C++, C#, and Java code.
  • doctest for unit testing only, fetched automatically in case of RPP_BUILD_TESTS enabled
  • trompeloeil for mocking in unit testing only, fetched automatically in case of RPP_BUILD_TESTS enabled
  • nanobench for benchmarking only, fetched automatically in case of RPP_BUILD_BENCHMARKS enabled
  • RxCpp only for comparison of performance between RPP and RxCpp in CI benchmarks. Used as cmake dependency under option
  • reactivex.io as source for insipration and definition of entities used in RPP. Some comments used in RPP source code taken from reactivex.io
  • rxmarbles python as generator of marbles graphs in doxygen documentation
  • cmake-init as generator for most part of initial CMakes
  • doxygen-awesome-css as CSS theme for doxygen documentation