// Add or update a client's subscription to ringer state changes in the // doubly-linked "subscriptions" list. void subscribe_client(struct sockaddr_in* client) { struct subscription_node* subscription_node = find_subscription_node(client); if(subscription_node == NULL) { // This client is not already in the list. struct subscription_node* node = make_subscription_node(make_subscription(client)); insert_subscription_node(node); } else { // The client is already in the list, update expiry time. struct timeval now; gettimeofday(&now, NULL); subscription_node->subscription.time = now.tv_sec; } }
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())); }
/** * @brief Starts the KP, initializes state and cals all necessary functions. * * @return 0. */ int main() { // Sets handler for CTR+C signal(SIGINT, &signal_callback_handler); // Initialize smart space information and data about subscription. ss_info_t info; subs_t subs; ss_init_space_info(&info, KP_SS_NAME, KP_SS_ADDRESS, KP_SS_PORT); subs.is_subscribed = false; subs.new_triples = NULL; subs.old_triples = NULL; // In the smart space the name of the KP must be unique, if you try to // join without leave, then you received an error. if (ss_join(&info, KP_NAME) == -1) { printf("Can't join to SS.\n"); return 0; } printf("KP join to SS.\n"); // Create a subscription to <KP-says-*> triples. if (make_subscription(&info, &subs) != 0) { printf("Can't subscribe.\n"); ss_leave(&info); return 0; } printf("\nWaiting new data.\n"); // Start subscription processing, it is ends: // - when yo press CTRL+C; // - when unsubscription indication will be received from the SS; // - on error. handle_subscription(&info, &subs); // Before leave we need to unsubscribe our subscription. handle_unsubscription(&info, &subs); // Delete triples list. update_subscription_triples(&subs, NULL, NULL); ss_leave(&info); printf("\nKP leave SS...\n"); return 0; }
void on_connect(composite_subscription cs) { if (connection.empty()) { // the lifetime of each connect is independent auto destination = subject_value.get_subscriber(); // when the paramter is unsubscribed it should // unsubscribe the most recent connection connection.reset(cs.add(destination.get_subscription())); // when the connection is finished it should shutdown the connection destination.add(make_subscription( [cs, this](){ cs.remove(this->connection.get()); this->connection.reset(); })); source.subscribe(destination); } }
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())); }