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
|