rxcpp:嵌套while循环或类似的" classic"程序的必要结构

时间:2016-12-29 05:46:19

标签: c++ reactive-programming rxcpp

我有一个可以传输某些事件的设备。我想使用反应式扩展来模拟以下行为:

  1. 检测用户何时连接加密狗(我的程序检查连接加密狗的事件)。
  2. 连接加密狗后,开始从加密狗捕获数据流。
  3. 能够检测到加密狗何时断开连接并返回1.以后如果用户再次连接加密狗,我想转到2.如果键盘被击中我流数据的状态,则程序结束
  4. 我知道如何等待加密狗连接(1。):

    void SomeListener (bool isClicked) {
        Debug.Log(isClicked);
    }
    
    //is there some way to do this?
    //void SomeListener(bool isClicker, string studentId) {
        //something
    //}}
    

    我知道如何捕获流(2。):

    auto waitForDongle = events.take_while([](auto const & event) {
          return event == DongleConnected
          }).subscribe([](auto) {});
    

    我的问题是我不知道如何组合流以便回到1.以及之后2.我只知道如何一次又一次地执行此操作。但我想要上述行为。

1 个答案:

答案 0 :(得分:6)

这与Rx中的常见UX拖动示例有关。在这种情况下,印刷机是加密狗连接,释放是加密狗移除。

此解决方案要求一次只能连接一个加密狗(预计在下一次连接之前删除)。事件中必须有更多信息才能允许多个连接重叠。

这是解决方案的核心。整个计划如下。

    auto DatasFromConnectedDongle = DongleConnects. // when connected
        map([=](DongleEvent const & event){
            assert(event == DongleEvent::Connected);
            cout << "Connected - " << flush;
            return DongleDatas. // return all the datas
                take_until(DongleRemoves). // stop when removed
                finally([](){
                    cout << "- Removed" << endl;
                });
        }).
        switch_on_next(). // only listen to datas from the most recent connected dongle
        take_until(Exits); // stop everything when key is pressed

我最终使用repeat(),但仅用于生成测试事件数据。

#include <rxcpp/rx.hpp>

namespace Rx {
using namespace rxcpp;
using namespace rxcpp::sources;
using namespace rxcpp::operators;
using namespace rxcpp::util;
}
using namespace Rx;

#include <cassert>
using namespace std;
using namespace std::chrono;

int main()
{
    //
    // test code
    //

    auto keyboardPressed = [](){
        return false;
    };

    enum class DongleEvent {
        Connected,
        Removed,
        Data,
        Other
    };
    auto events = from(
            DongleEvent::Data, DongleEvent::Other, 
            DongleEvent::Connected, DongleEvent::Data, 
            DongleEvent::Other, DongleEvent::Other, 
            DongleEvent::Data, DongleEvent::Removed, 
            DongleEvent::Other, DongleEvent::Data).
        repeat(5). // send the above events five times over
        zip(take_at<0>(), interval(milliseconds(200))). // pace our test data
        publish().
        ref_count(); // publish and ref_count make the events sharable

    //
    // the solution
    //

    // fires when connected
    auto DongleConnects = events.
        filter([](DongleEvent const & event) {
            return event == DongleEvent::Connected;
        });

    // fires when data arrives
    auto DongleDatas = events.
        filter([](DongleEvent const & event) {
            return event == DongleEvent::Data;
        });

    // fires when removed    
    auto DongleRemoves = events.
        filter([](DongleEvent const & event) {
            return event == DongleEvent::Removed;
        });

    // fires when key pressed    
    auto Exits = interval(milliseconds(200)).
        filter([=](long){
            return keyboardPressed();
        });

    auto DatasFromConnectedDongle = DongleConnects.
        map([=](DongleEvent const & event){
            assert(event == DongleEvent::Connected);
            cout << "Connected - " << flush;
            return DongleDatas. // return all the datas
                take_until(DongleRemoves). // stop when removed
                finally([](){
                    cout << "- Removed" << endl;
                });
        }).
        switch_on_next(). // only listen to datas from the most recent connected dongle
        take_until(Exits); // stop everything when key is pressed

    DatasFromConnectedDongle.subscribe([](DongleEvent const & event){
        assert(event == DongleEvent::Data);
        cout << "Data " << flush;
    });

    return 0;
}

产生

~/source/rxcpp/Rx/v2/examples/dongle (master)$ cmake .
...
~/source/rxcpp/Rx/v2/examples/dongle (master)$ make
Scanning dependencies of target dongle
[ 50%] Building CXX object CMakeFiles/dongle.dir/main.cpp.o
[100%] Linking CXX executable dongle
[100%] Built target dongle
~/source/rxcpp/Rx/v2/examples/dongle (master)$ ./dongle 
Connected - Data Data - Removed
Connected - Data Data - Removed
Connected - Data Data - Removed
Connected - Data Data - Removed
Connected - Data Data - Removed
~/source/rxcpp/Rx/v2/examples/dongle (master)$