• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2 
3 #pragma once
4 
5 /*! \file rx-repeat.hpp
6 
7     \brief Repeat this observable for the given number of times or infinitely.
8 
9     \tparam Count  the type of the counter (optional).
10 
11     \param t The number of times the source observable items are repeated (optional). If not specified, infinitely repeats the source observable. Specifying 0 returns an empty sequence immediately
12 
13     \return  An observable that repeats the sequence of items emitted by the source observable for t times.
14 
15     \sample
16     \snippet repeat.cpp repeat count sample
17     \snippet output.txt repeat count sample
18 
19     If the source observable calls on_error, repeat stops:
20     \snippet repeat.cpp repeat error sample
21     \snippet output.txt repeat error sample
22 */
23 
24 #if !defined(RXCPP_OPERATORS_RX_REPEAT_HPP)
25 #define RXCPP_OPERATORS_RX_REPEAT_HPP
26 
27 #include "../rx-includes.hpp"
28 #include "rx-retry-repeat-common.hpp"
29 
30 namespace rxcpp {
31 
32 namespace operators {
33 
34 namespace detail {
35 
36 template<class... AN>
37 struct repeat_invalid_arguments {};
38 
39 template<class... AN>
40 struct repeat_invalid : public rxo::operator_base<repeat_invalid_arguments<AN...>> {
41     using type = observable<repeat_invalid_arguments<AN...>, repeat_invalid<AN...>>;
42 };
43 template<class... AN>
44 using repeat_invalid_t = typename repeat_invalid<AN...>::type;
45 
46 // Contain repeat variations in a namespace
47 namespace repeat {
48   struct event_handlers {
49     template <typename State>
on_errorrxcpp::operators::detail::repeat::event_handlers50     static inline void on_error(State& state, rxu::error_ptr& e) {
51       state->out.on_error(e);
52     }
53 
54     template <typename State>
on_completedrxcpp::operators::detail::repeat::event_handlers55     static inline void on_completed(State& state) {
56       // Functions update() and completed_predicate() vary between finite and infinte versions
57       state->update();
58       if (state->completed_predicate()) {
59         state->out.on_completed();
60       } else {
61         state->do_subscribe();
62       }
63     }
64   };
65 
66   // Finite repeat case (explicitely limited with the number of times)
67   template <class T, class Observable, class Count>
68   using finite = ::rxcpp::operators::detail::retry_repeat_common::finite
69     <event_handlers, T, Observable, Count>;
70 
71   // Infinite repeat case
72   template <class T, class Observable>
73   using infinite = ::rxcpp::operators::detail::retry_repeat_common::infinite
74     <event_handlers, T, Observable>;
75 
76 }
77 } // detail
78 
79 /*! @copydoc rx-repeat.hpp
80 */
81 template<class... AN>
repeat(AN &&...an)82 auto repeat(AN&&... an)
83 ->     operator_factory<repeat_tag, AN...> {
84     return operator_factory<repeat_tag, AN...>(std::make_tuple(std::forward<AN>(an)...));
85 }
86 
87 }
88 
89 template<>
90 struct member_overload<repeat_tag> {
91   template<class Observable,
92            class Enabled = rxu::enable_if_all_true_type_t<is_observable<Observable>>,
93            class SourceValue = rxu::value_type_t<Observable>,
94            class Repeat = rxo::detail::repeat::infinite<SourceValue, rxu::decay_t<Observable>>,
95            class Value = rxu::value_type_t<Repeat>,
96            class Result = observable<Value, Repeat>>
memberrxcpp::member_overload97   static Result member(Observable&& o) {
98     return Result(Repeat(std::forward<Observable>(o)));
99   }
100 
101   template<class Observable,
102            class Count,
103            class Enabled = rxu::enable_if_all_true_type_t<is_observable<Observable>>,
104            class SourceValue = rxu::value_type_t<Observable>,
105            class Repeat = rxo::detail::repeat::finite<SourceValue, rxu::decay_t<Observable>, rxu::decay_t<Count>>,
106            class Value = rxu::value_type_t<Repeat>,
107            class Result = observable<Value, Repeat>>
memberrxcpp::member_overload108   static Result member(Observable&& o, Count&& c) {
109     return Result(Repeat(std::forward<Observable>(o), std::forward<Count>(c)));
110   }
111 
112   template<class... AN>
memberrxcpp::member_overload113   static operators::detail::repeat_invalid_t<AN...> member(AN...) {
114     std::terminate();
115     return {};
116     static_assert(sizeof...(AN) == 10000, "repeat takes (optional Count)");
117   }
118 };
119 
120 }
121 
122 #endif
123