-
Notifications
You must be signed in to change notification settings - Fork 37
Add timeout with fallback observable #302
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -7,36 +7,61 @@ | |||||
| **/ | ||||||
| int main() | ||||||
| { | ||||||
| //! [timeout] | ||||||
| rpp::subjects::publish_subject<int> subj{}; | ||||||
| subj.get_observable() | ||||||
| .timeout(std::chrono::milliseconds{450}, rpp::schedulers::new_thread{}) | ||||||
| .subscribe([](int v) { std::cout << "new value " << v << std::endl; }, | ||||||
| [](std::exception_ptr err) | ||||||
| { | ||||||
| try | ||||||
| { | ||||||
| std::rethrow_exception(err); | ||||||
| } | ||||||
| catch (const std::exception& exc) | ||||||
| { | ||||||
| //! [timeout] | ||||||
| rpp::subjects::publish_subject<int> subj{}; | ||||||
| subj.get_observable() | ||||||
| .timeout(std::chrono::milliseconds{450}, rpp::schedulers::new_thread{}) | ||||||
| .subscribe([](int v) { std::cout << "new value " << v << std::endl; }, | ||||||
| [](std::exception_ptr err) | ||||||
| { | ||||||
| std::cout << "ERR: " << exc.what() << std::endl; | ||||||
| } | ||||||
| }, | ||||||
| []() { std::cout << "completed" << std::endl; }); | ||||||
| for (int i = 0; i < 10; ++i) | ||||||
| try | ||||||
| { | ||||||
| std::rethrow_exception(err); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| } | ||||||
| catch (const std::exception& exc) | ||||||
| { | ||||||
| std::cout << "ERR: " << exc.what() << std::endl; | ||||||
| } | ||||||
| }, | ||||||
| []() { std::cout << "completed" << std::endl; }); | ||||||
| for (int i = 0; i < 10; ++i) | ||||||
| { | ||||||
| std::this_thread::sleep_for(std::chrono::milliseconds{i * 100}); | ||||||
| subj.get_subscriber().on_next(i); | ||||||
| } | ||||||
|
|
||||||
| // Output: | ||||||
| // new value 0 | ||||||
| // new value 1 | ||||||
| // new value 2 | ||||||
| // new value 3 | ||||||
| // new value 4 | ||||||
| // ERR : Timeout reached | ||||||
| //! [timeout] | ||||||
| } | ||||||
| { | ||||||
| std::this_thread::sleep_for(std::chrono::milliseconds{i * 100}); | ||||||
| subj.get_subscriber().on_next(i); | ||||||
| //! [timeout_fallback_obs] | ||||||
| rpp::subjects::publish_subject<int> subj{}; | ||||||
| subj.get_observable() | ||||||
| .timeout(std::chrono::milliseconds{450}, rpp::source::just(100), rpp::schedulers::new_thread{}) | ||||||
| .subscribe([](int v) { std::cout << "new value " << v << std::endl; }, | ||||||
| []() { std::cout << "completed" << std::endl; }); | ||||||
| for (int i = 0; i < 10; ++i) | ||||||
| { | ||||||
| std::this_thread::sleep_for(std::chrono::milliseconds{i * 100}); | ||||||
| subj.get_subscriber().on_next(i); | ||||||
| } | ||||||
|
|
||||||
| // Output: | ||||||
| //new value 0 | ||||||
| //new value 1 | ||||||
| //new value 2 | ||||||
| //new value 3 | ||||||
| //new value 4 | ||||||
| //new value 100 | ||||||
| //completed | ||||||
| //! [timeout_fallback_obs] | ||||||
| } | ||||||
|
|
||||||
| // Output: | ||||||
| // new value 0 | ||||||
| // new value 1 | ||||||
| // new value 2 | ||||||
| // new value 3 | ||||||
| // new value 4 | ||||||
| // ERR : Timeout reached | ||||||
| //! [timeout] | ||||||
| return 0; | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -11,7 +11,8 @@ | |||||
| #pragma once | ||||||
|
|
||||||
| #include <rpp/schedulers/constraints.hpp> | ||||||
|
|
||||||
| #include <rpp/sources/fwd.hpp> | ||||||
| #include <rpp/observables/constraints.hpp> | ||||||
| #include <rpp/observables/details/member_overload.hpp> | ||||||
|
|
||||||
| namespace rpp::details | ||||||
|
|
@@ -21,12 +22,44 @@ struct timeout_tag; | |||||
|
|
||||||
| namespace rpp::details | ||||||
| { | ||||||
| template<constraint::decayed_type Type, schedulers::constraint::scheduler TScheduler> | ||||||
| template<constraint::decayed_type Type, constraint::observable_of_type<Type> FallbackObs, schedulers::constraint::scheduler TScheduler> | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| struct timeout_impl; | ||||||
|
|
||||||
| template<constraint::decayed_type Type, typename SpecificObservable> | ||||||
| struct member_overload<Type, SpecificObservable, timeout_tag> | ||||||
| { | ||||||
| /** | ||||||
| * \brief Forwards emissions from original observable, but subscribes on fallback observable if no any events during specified period of time (since last emission) | ||||||
| * | ||||||
| * \marble timeout_fallback_obs | ||||||
| { | ||||||
| source observable : +--1-2-3-4----- ---5-| | ||||||
| operator "timeout(4, -10-|)" : +--1-2-3-4----10-| | ||||||
| } | ||||||
| * \param period is maximum duration between emitted items before a timeout occurs | ||||||
| * \param fallback_obs is observable to subscribe on when timeout reached | ||||||
| * \param scheduler is scheduler used to run timer for timeout | ||||||
| * \return new specific_observable with the timeout operator as most recent operator. | ||||||
| * \warning #include <rpp/operators/timeout.hpp> | ||||||
| * | ||||||
| * \par Example | ||||||
| * \snippet timeout.cpp timeout_fallback_obs | ||||||
| * | ||||||
| * \ingroup utility_operators | ||||||
| * \see https://reactivex.io/documentation/operators/timeout.html | ||||||
| */ | ||||||
| template<constraint::observable_of_type<Type> FallbackObs, schedulers::constraint::scheduler TScheduler> | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| auto timeout(schedulers::duration period, FallbackObs&& fallback_obs, const TScheduler& scheduler = TScheduler{}) const & requires is_header_included<timeout_tag, FallbackObs, TScheduler> | ||||||
| { | ||||||
| return static_cast<const SpecificObservable*>(this)->template lift<Type>(timeout_impl<Type, std::decay_t<FallbackObs>, TScheduler>{period, std::forward<FallbackObs>(fallback_obs), scheduler}); | ||||||
| } | ||||||
|
|
||||||
| template<constraint::observable_of_type<Type> FallbackObs,schedulers::constraint::scheduler TScheduler> | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| auto timeout(schedulers::duration period, FallbackObs&& fallback_obs, const TScheduler& scheduler = TScheduler{}) && requires is_header_included<timeout_tag, FallbackObs, TScheduler> | ||||||
| { | ||||||
| return std::move(*static_cast<SpecificObservable*>(this)).template lift<Type>(timeout_impl<Type, std::decay_t<FallbackObs>, TScheduler>{period, std::forward<FallbackObs>(fallback_obs), scheduler}); | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * \brief Forwards emissions from original observable, but emit error if no any events during specified period of time (since last emission) | ||||||
| * | ||||||
|
|
@@ -49,13 +82,15 @@ struct member_overload<Type, SpecificObservable, timeout_tag> | |||||
| template<schedulers::constraint::scheduler TScheduler> | ||||||
| auto timeout(schedulers::duration period, const TScheduler& scheduler = TScheduler{}) const & requires is_header_included<timeout_tag, TScheduler> | ||||||
| { | ||||||
| return static_cast<const SpecificObservable*>(this)->template lift<Type>(timeout_impl<Type, TScheduler>{period, scheduler}); | ||||||
| return timeout(period, rpp::source::error<Type>(std::make_exception_ptr(utils::timeout{"Timeout reached"})), scheduler); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||
| } | ||||||
|
|
||||||
| template<schedulers::constraint::scheduler TScheduler> | ||||||
| auto timeout(schedulers::duration period, const TScheduler& scheduler = TScheduler{}) && requires is_header_included<timeout_tag, TScheduler> | ||||||
| { | ||||||
| return std::move(*static_cast<SpecificObservable*>(this)).template lift<Type>(timeout_impl<Type, TScheduler>{period, scheduler}); | ||||||
| return std::move(*static_cast<SpecificObservable*>(this)).timeout(period, rpp::source::error<Type>(std::make_exception_ptr(utils::timeout{"Timeout reached"})), scheduler); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||
| } | ||||||
|
|
||||||
|
|
||||||
| }; | ||||||
| } // namespace rpp::details | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parameter
erris passed by value and only copied once; consider moving it to avoid unnecessary copies