This project is read-only.
1
Vote

move lambda capture for observable doesn't work

description

Hi, First I really appreciate the work you guys have done on RxCpp, it is great thanks.

I'm not really sure if this is a bug or a feature request. I wanted to mimic some of the observable creation mechanisms from RxJava and Rx.Net in RxCpp. I was starting with fromFuture, unfortunately (at least the way I was going about it) I need to capture the future by move, here is a simple example:
int main(void) {
  std::cout << "RxCppLambdaBugMain: " << std::endl;

  std::promise<int> p{};
  auto f = p.get_future();
  auto func = [&p]() {
    std::this_thread::sleep_for(2s);
    p.set_value(9);
  };

  auto o =
      rx::observable<>::create<int>([cf = std::move(f)](
                                        rx::subscriber<int> s) /* mutable */ {
        try {
          auto val = cf.get();
          s.on_next(val);
          s.on_completed();
        } catch (const std::exception& e) {
          s.on_error(std::make_exception_ptr(e));
        }
      }).subscribe_on(rx::serialize_new_thread());

  func();

  auto s1 = o.subscribe(
      [](auto n) {
        std::cout << "S1 Rx'd event: " << n
                  << " on: " << std::this_thread::get_id() << std::endl;
      },
      [](std::exception_ptr ePtr) {
        try {
          std::rethrow_exception(ePtr);
        } catch (const std::exception e) {
          std::cout << "S1 exception: " << e.what()
                    << " on: " << std::this_thread::get_id() << std::endl;
        }
      },
      []() {
        std::cout << "S1 completed on: " << std::this_thread::get_id()
                  << std::endl;
      });

  return 0;
}
Using "mutable" the code won't compile, so I have to use "-fpermissive" in gcc. I suppose "get" changes the state of the future, and since it is const that isn't allowed. The reason I think this is a bug is that part of the problem comes from the future being copied deep in the RxCpp code. You can fix some of those issues by moving "source_operator" vs. copying in rx-observable.hpp (eg. the "lift" operator).

You run into even more problems when using "observe_on" and subscribe_on".

The two main sources of errors seem to be:
1.) copy vs move semantics in various places in the RxCpp code.
2.) const issues, when trying to use "mutable".

I tried to track these down but following the template logic is really hard. For now I'm using a shared future but it would be really nice to move-capture in observable lambdas. Let me know if I need to provide more info, or if there is anything I can do. Thanks.

comments