Reactive Stream Processing Rx4DDS - Sumant Tambe - CppCon 2015
Reactive Stream Processing Rx4DDS - Sumant Tambe - CppCon 2015
Elastic/Scalable: Scales
easily up/down with load
and cpu cores. Event-Driven
Streaming
Sensors Events
Data
Real-Time Enterprise
Actuators
Applications Applications
FILTER FILTER
Application
DDS-C++ DDS-JAVA* DDS-IDL-C DDS-IDL-C#
DDS-SECURITY
DDS-XTYPES
DDS-RPC*
RTPS v2.2
HTTP(s) UDP TCP** DTLS** TLS** SHARED-
IP MEMORY**
© 2015 RTI
12
STANDARD
API
Choice
AWESOME
9/21/2015 © 2015 RTI 13
A**
i/p
o/p
Pull Push
IEnumerator<out T> IObserver<in T>
T Current { get; } void OnNext(T value)
bool MoveNext() void OnCompleted()
void OnError(Exception ex)
Duality (video):
http://channel9.msdn.com/Shows/Going+Deep/Expert-to-Expert-Brian-Beckman-and-Erik-Meijer-Inside-the-NET-Reactive-Framework-Rx
Credit: rxmarbles.com
Observable Observer
DataReader
DataWriter
DataReader
DataWriter
Processing
DataReader
class ShapeType
{
string color; //@key
int shapesize;
int x;
int y;
}
rx::observable<LoanedSample<ShapeType>> source =
topic_sub.create_observable();
rx::observable<ShapeType> square_track =
source >> rx4dds::complete_on_dispose()
>> rx4dds::error_on_no_alive_writers()
>> filter([](LoanedSample<ShapeType> s) {
return s.info().valid();
}) // skip invalid samples
>> map([](LoanedSample<ShapeType> valid) {
return valid.data();
}); // map samples to data
9/21/2015 Real-Time Innovations, Inc. 32
Map to Circle Track
int circle_degree = 0;
rx::observable<ShapeType> circle_track =
square_track
.map([circle_degree](ShapeType & square) mutable
{
circle_degree = (circle_degree + 3) % 360;
return shape_location(square, circle_degree);
})
.tap([circle_writer](ShapeType & circle) mutable {
circle_writer.write(circle);
}); // tap replaced as publish_over_dds later
rx::observable<ShapeType> triangle_track =
circle_track
.map([tri_degree](ShapeType & circle) mutable
{
tri_degree = (tri_degree + 9) % 360;
return shape_location(circle, tri_degree);
})
>> rx4dds::publish_over_dds(triangle_writer);
triangle_track.subscribe();
auto skip_invalid_samples()
{
return [](auto src_observable) {
return src_observable
.filter([](auto & sample) {
return sample.info().valid()
});
};
}
Source:
9/21/2015
Google Images Real-Time Innovations, Inc. 37
Data Pipelines Demo Next
i/p
o/p
auto grouped_stream =
topic_sub.create_observable()
>> group_by_instance ([](ShapeType & shape) {
return shape.color();
});
decltype(grouped_stream) ===
rx::observable<
rx::grouped_observable<
string, LoanedSample<ShapeType>
>
>
9/21/2015 Real-Time Innovations, Inc. 40
grouped_stream
.flat_map([circle_writer, triangle_writer]
(GroupedShapeObservable go) {
rx::observable<ShapeType> inner_transformed =
go >> to_unkeyed()
>> complete_on_dispose()
>> error_on_no_alive_writers()
>> skip_invalid_samples()
>> map_samples_to_data()
>> map_to_circle_track() // as shown before
>> publish_over_dds(
circle_writer, ShapeType(go.key())
>> map_to_triangle_track() // as shown before
>> publish_over_dds(
triangle_writer, ShapeType(go.key());
return inner_transformed;
}).subscribe();
9/21/2015 © Real-Time Innovations, Inc. 41
Dynamic Correlator