122 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			122 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|   | // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
 | ||
|  | 
 | ||
|  | #pragma once
 | ||
|  | 
 | ||
|  | /*! \file rx-retry.hpp
 | ||
|  | 
 | ||
|  |     \brief Retry this observable for the given number of times. | ||
|  | 
 | ||
|  |     \tparam Count the type of the counter (optional) | ||
|  | 
 | ||
|  |     \param t  the total number of tries (optional), i.e. retry(2) means one normal try, before an error occurs, and one retry. If not specified, infinitely retries the source observable. Specifying 0 returns immediately without subscribing | ||
|  | 
 | ||
|  |     \return  An observable that mirrors the source observable, resubscribing to it if it calls on_error up to a specified number of retries. | ||
|  | 
 | ||
|  |     \sample | ||
|  |     \snippet retry.cpp retry count sample | ||
|  |     \snippet output.txt retry count sample | ||
|  | */ | ||
|  | 
 | ||
|  | #if !defined(RXCPP_OPERATORS_RX_RETRY_HPP)
 | ||
|  | #define RXCPP_OPERATORS_RX_RETRY_HPP
 | ||
|  | 
 | ||
|  | #include "../rx-includes.hpp"
 | ||
|  | #include "rx-retry-repeat-common.hpp"
 | ||
|  | 
 | ||
|  | namespace rxcpp { | ||
|  | 
 | ||
|  | namespace operators { | ||
|  | 
 | ||
|  | namespace detail { | ||
|  | 
 | ||
|  | template<class... AN> | ||
|  | struct retry_invalid_arguments {}; | ||
|  | 
 | ||
|  | template<class... AN> | ||
|  | struct retry_invalid : public rxo::operator_base<retry_invalid_arguments<AN...>> { | ||
|  |   using type = observable<retry_invalid_arguments<AN...>, retry_invalid<AN...>>; | ||
|  | }; | ||
|  | template<class... AN> | ||
|  | using retry_invalid_t = typename retry_invalid<AN...>::type; | ||
|  | 
 | ||
|  | // Contain retry variations in a namespace
 | ||
|  | namespace retry { | ||
|  |   struct event_handlers { | ||
|  |     template <typename State> | ||
|  |     static inline void on_error(State& state, rxu::error_ptr& e) { | ||
|  |       state->update(); | ||
|  |       // Use specialized predicate for finite/infinte case
 | ||
|  |       if (state->completed_predicate()) { | ||
|  |         state->out.on_error(e);                                   | ||
|  |       } else { | ||
|  |         state->do_subscribe(); | ||
|  |       } | ||
|  |     } | ||
|  |            | ||
|  |     template <typename State> | ||
|  |     static inline void on_completed(State& state) { | ||
|  |       state->out.on_completed(); | ||
|  |     } | ||
|  |   }; | ||
|  | 
 | ||
|  |   // Finite repeat case (explicitely limited with the number of times)
 | ||
|  |   template <class T, class Observable, class Count> | ||
|  |   using finite = ::rxcpp::operators::detail::retry_repeat_common::finite | ||
|  |     <event_handlers, T, Observable, Count>; | ||
|  |    | ||
|  |   // Infinite repeat case
 | ||
|  |   template <class T, class Observable> | ||
|  |   using infinite = ::rxcpp::operators::detail::retry_repeat_common::infinite | ||
|  |     <event_handlers, T, Observable>; | ||
|  |    | ||
|  | } | ||
|  | } // detail
 | ||
|  | 
 | ||
|  | /*! @copydoc rx-retry.hpp
 | ||
|  | */ | ||
|  | template<class... AN> | ||
|  | auto retry(AN&&... an) | ||
|  | ->     operator_factory<retry_tag, AN...> { | ||
|  |     return operator_factory<retry_tag, AN...>(std::make_tuple(std::forward<AN>(an)...)); | ||
|  | }     | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | template<>  | ||
|  | struct member_overload<retry_tag> | ||
|  | { | ||
|  |   template<class Observable, | ||
|  |            class Enabled = rxu::enable_if_all_true_type_t<is_observable<Observable>>, | ||
|  |            class SourceValue = rxu::value_type_t<Observable>, | ||
|  |            class Retry = rxo::detail::retry::infinite<SourceValue, rxu::decay_t<Observable>>, | ||
|  |            class Value = rxu::value_type_t<Retry>, | ||
|  |            class Result = observable<Value, Retry> | ||
|  |            > | ||
|  |   static Result member(Observable&& o) { | ||
|  |     return Result(Retry(std::forward<Observable>(o))); | ||
|  |   } | ||
|  | 
 | ||
|  |   template<class Observable, | ||
|  |            class Count, | ||
|  |            class Enabled = rxu::enable_if_all_true_type_t<is_observable<Observable>>, | ||
|  |            class SourceValue = rxu::value_type_t<Observable>, | ||
|  |            class Retry = rxo::detail::retry::finite<SourceValue, rxu::decay_t<Observable>, rxu::decay_t<Count>>, | ||
|  |            class Value = rxu::value_type_t<Retry>, | ||
|  |            class Result = observable<Value, Retry> | ||
|  |            > | ||
|  |   static Result member(Observable&& o, Count&& c) { | ||
|  |     return Result(Retry(std::forward<Observable>(o), std::forward<Count>(c))); | ||
|  |   } | ||
|  | 
 | ||
|  |   template<class... AN> | ||
|  |   static operators::detail::retry_invalid_t<AN...> member(const AN&...) { | ||
|  |     std::terminate(); | ||
|  |     return {}; | ||
|  |     static_assert(sizeof...(AN) == 10000, "retry takes (optional Count)"); | ||
|  |   }  | ||
|  | }; | ||
|  |      | ||
|  | } | ||
|  | 
 | ||
|  | #endif
 |