void on_subscribe(Subscriber o) const { struct state_type : public std::enable_shared_from_this<state_type> , public values { state_type(values i_, Subscriber o_) : values(i_) , out(std::move(o_)) { } Subscriber out; rxu::detail::maybe<resource_type> resource; }; auto state = std::make_shared<state_type>(state_type(initial, std::move(o))); state->resource = on_exception( [&](){return state->resource_factory(); }, state->out); if (state->resource.empty()) { return; } state->out.add(state->resource->get_subscription()); auto selectedCollection = on_exception( [state](){return state->observable_factory(state->resource.get()); }, state->out); if (selectedCollection.empty()) { return; } selectedCollection->subscribe(state->out); }
void subscribe_to(collection_type st) { auto state = this->shared_from_this(); collectionLifetime = composite_subscription(); // when the out observer is unsubscribed all the // inner subscriptions are unsubscribed as well auto innercstoken = state->out.add(collectionLifetime); collectionLifetime.add(make_subscription([state, innercstoken](){ state->out.remove(innercstoken); })); auto selectedSource = on_exception( [&](){return state->coordinator.in(std::move(st));}, state->out); if (selectedSource.empty()) { return; } // this subscribe does not share the out subscription // so that when it is unsubscribed the out will continue auto sinkInner = make_subscriber<value_type>( state->out, collectionLifetime, // on_next [state, st](value_type ct) { state->out.on_next(ct); }, // on_error [state](std::exception_ptr e) { state->out.on_error(e); }, //on_completed [state](){ if (!state->selectedCollections.empty()) { auto value = state->selectedCollections.front(); state->selectedCollections.pop_front(); state->collectionLifetime.unsubscribe(); state->subscribe_to(value); } else if (!state->sourceLifetime.is_subscribed()) { state->out.on_completed(); } } ); auto selectedSinkInner = on_exception( [&](){return state->coordinator.out(sinkInner);}, state->out); if (selectedSinkInner.empty()) { return; } selectedSource->subscribe(std::move(selectedSinkInner.get())); }
void on_subscribe(Subscriber o) const { on_exception( [&](){ this->on_subscribe_function(o); return true; }, o); }
void on_subscribe(Subscriber o) const { static_assert(is_subscriber<Subscriber>::value, "subscribe must be passed a subscriber"); // creates a worker whose lifetime is the same as this subscription auto coordinator = initial.coordination.create_coordinator(o.get_subscription()); auto controller = coordinator.get_worker(); auto counter = std::make_shared<long>(0); auto producer = [o, counter](const rxsc::schedulable&) { // send next value o.on_next(++(*counter)); }; auto selectedProducer = on_exception( [&](){return coordinator.act(producer);}, o); if (selectedProducer.empty()) { return; } controller.schedule_periodically(initial.initial, initial.period, selectedProducer.get()); }
void on_subscribe(Subscriber scbr) const { static_assert(is_subscriber<Subscriber>::value, "subscribe must be passed a subscriber"); typedef Subscriber output_type; struct merge_state_type : public std::enable_shared_from_this<merge_state_type> , public values { merge_state_type(values i, coordinator_type coor, output_type oarg) : values(i) , source(i.source_operator) , pendingCompletions(0) , coordinator(std::move(coor)) , out(std::move(oarg)) { } observable<source_value_type, source_operator_type> source; // on_completed on the output must wait until all the // subscriptions have received on_completed int pendingCompletions; coordinator_type coordinator; output_type out; }; auto coordinator = initial.coordination.create_coordinator(scbr.get_subscription()); // take a copy of the values for each subscription auto state = std::shared_ptr<merge_state_type>(new merge_state_type(initial, std::move(coordinator), std::move(scbr))); composite_subscription outercs; // when the out observer is unsubscribed all the // inner subscriptions are unsubscribed as well state->out.add(outercs); auto source = on_exception( [&](){return state->coordinator.in(state->source);}, state->out); if (source.empty()) { return; } ++state->pendingCompletions; // this subscribe does not share the observer subscription // so that when it is unsubscribed the observer can be called // until the inner subscriptions have finished auto sink = make_subscriber<source_value_type>( state->out, outercs, // on_next [state](source_value_type st) { composite_subscription innercs; // when the out observer is unsubscribed all the // inner subscriptions are unsubscribed as well auto innercstoken = state->out.add(innercs); innercs.add(make_subscription([state, innercstoken](){ state->out.remove(innercstoken); })); auto selectedSource = on_exception( [&](){return state->coordinator.in(st);}, state->out); if (selectedSource.empty()) { return; } ++state->pendingCompletions; // this subscribe does not share the source subscription // so that when it is unsubscribed the source will continue auto sinkInner = make_subscriber<value_type>( state->out, innercs, // on_next [state, st](value_type ct) { state->out.on_next(std::move(ct)); }, // on_error [state](std::exception_ptr e) { state->out.on_error(e); }, //on_completed [state](){ if (--state->pendingCompletions == 0) { state->out.on_completed(); } } ); auto selectedSinkInner = on_exception( [&](){return state->coordinator.out(sinkInner);}, state->out); if (selectedSinkInner.empty()) { return; } selectedSource->subscribe(std::move(selectedSinkInner.get())); }, // on_error [state](std::exception_ptr e) { state->out.on_error(e); }, // on_completed [state]() { if (--state->pendingCompletions == 0) { state->out.on_completed(); } } ); auto selectedSink = on_exception( [&](){return state->coordinator.out(sink);}, state->out); if (selectedSink.empty()) { return; } source->subscribe(std::move(selectedSink.get())); }
void on_subscribe(Subscriber s) const { typedef Subscriber output_type; struct state_type : public std::enable_shared_from_this<state_type> , public values { state_type(const values& i, coordinator_type coor, const output_type& oarg) : values(i) , mode_value(mode::skipping) , coordinator(std::move(coor)) , out(oarg) { out.add(trigger_lifetime); out.add(source_lifetime); } typename mode::type mode_value; composite_subscription trigger_lifetime; composite_subscription source_lifetime; coordinator_type coordinator; output_type out; }; auto coordinator = initial.coordination.create_coordinator(); // take a copy of the values for each subscription auto state = std::shared_ptr<state_type>(new state_type(initial, std::move(coordinator), std::move(s))); auto trigger = on_exception( [&](){return state->coordinator.in(state->trigger);}, state->out); if (trigger.empty()) { return; } auto source = on_exception( [&](){return state->coordinator.in(state->source);}, state->out); if (source.empty()) { return; } auto sinkTrigger = make_subscriber<typename trigger_source_type::value_type>( // share parts of subscription state->out, // new lifetime state->trigger_lifetime, // on_next [state](const typename trigger_source_type::value_type&) { if (state->mode_value != mode::skipping) { return; } state->mode_value = mode::triggered; state->trigger_lifetime.unsubscribe(); }, // on_error [state](std::exception_ptr e) { if (state->mode_value != mode::skipping) { return; } state->mode_value = mode::errored; state->out.on_error(e); }, // on_completed [state]() { if (state->mode_value != mode::skipping) { return; } state->mode_value = mode::clear; state->trigger_lifetime.unsubscribe(); } ); auto selectedSinkTrigger = on_exception( [&](){return state->coordinator.out(sinkTrigger);}, state->out); if (selectedSinkTrigger.empty()) { return; } trigger->subscribe(std::move(selectedSinkTrigger.get())); source.get().subscribe( // split subscription lifetime state->source_lifetime, // on_next [state](T t) { if (state->mode_value != mode::triggered) { return; } state->out.on_next(t); }, // on_error [state](std::exception_ptr e) { if (state->mode_value > mode::triggered) { return; } state->mode_value = mode::errored; state->out.on_error(e); }, // on_completed [state]() { if (state->mode_value != mode::triggered) { return; } state->mode_value = mode::stopped; state->out.on_completed(); } ); }
void on_subscribe(Subscriber scbr) const { static_assert(is_subscriber<Subscriber>::value, "subscribe must be passed a subscriber"); typedef Subscriber output_type; struct concat_state_type : public std::enable_shared_from_this<concat_state_type> , public values { concat_state_type(values i, coordinator_type coor, output_type oarg) : values(std::move(i)) , sourceLifetime(composite_subscription::empty()) , collectionLifetime(composite_subscription::empty()) , coordinator(std::move(coor)) , out(std::move(oarg)) { } void subscribe_to(collection_type st) { auto state = this->shared_from_this(); collectionLifetime = composite_subscription(); // when the out observer is unsubscribed all the // inner subscriptions are unsubscribed as well auto innercstoken = state->out.add(collectionLifetime); collectionLifetime.add(make_subscription([state, innercstoken](){ state->out.remove(innercstoken); })); auto selectedSource = on_exception( [&](){return state->coordinator.in(std::move(st));}, state->out); if (selectedSource.empty()) { return; } // this subscribe does not share the out subscription // so that when it is unsubscribed the out will continue auto sinkInner = make_subscriber<value_type>( state->out, collectionLifetime, // on_next [state, st](value_type ct) { state->out.on_next(ct); }, // on_error [state](std::exception_ptr e) { state->out.on_error(e); }, //on_completed [state](){ if (!state->selectedCollections.empty()) { auto value = state->selectedCollections.front(); state->selectedCollections.pop_front(); state->collectionLifetime.unsubscribe(); state->subscribe_to(value); } else if (!state->sourceLifetime.is_subscribed()) { state->out.on_completed(); } } ); auto selectedSinkInner = on_exception( [&](){return state->coordinator.out(sinkInner);}, state->out); if (selectedSinkInner.empty()) { return; } selectedSource->subscribe(std::move(selectedSinkInner.get())); } composite_subscription sourceLifetime; composite_subscription collectionLifetime; std::deque<collection_type> selectedCollections; coordinator_type coordinator; output_type out; }; auto coordinator = initial.coordination.create_coordinator(scbr.get_subscription()); // take a copy of the values for each subscription auto state = std::shared_ptr<concat_state_type>(new concat_state_type(initial, std::move(coordinator), std::move(scbr))); state->sourceLifetime = composite_subscription(); // when the out observer is unsubscribed all the // inner subscriptions are unsubscribed as well state->out.add(state->sourceLifetime); auto source = on_exception( [&](){return state->coordinator.in(state->source);}, state->out); if (source.empty()) { return; } // this subscribe does not share the observer subscription // so that when it is unsubscribed the observer can be called // until the inner subscriptions have finished auto sink = make_subscriber<collection_type>( state->out, state->sourceLifetime, // on_next [state](collection_type st) { if (state->collectionLifetime.is_subscribed()) { state->selectedCollections.push_back(st); } else if (state->selectedCollections.empty()) { state->subscribe_to(st); } }, // on_error [state](std::exception_ptr e) { state->out.on_error(e); }, // on_completed [state]() { if (!state->collectionLifetime.is_subscribed() && state->selectedCollections.empty()) { state->out.on_completed(); } } ); auto selectedSink = on_exception( [&](){return state->coordinator.out(sink);}, state->out); if (selectedSink.empty()) { return; } source->subscribe(std::move(selectedSink.get())); }