• 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 #if !defined(RXCPP_SOURCES_RX_SCOPE_HPP)
6 #define RXCPP_SOURCES_RX_SCOPE_HPP
7 
8 #include "../rx-includes.hpp"
9 
10 /*! \file rx-scope.hpp
11 
12     \brief Returns an observable that makes an observable by the specified observable factory using the resource provided by the specified resource factory for each new observer that subscribes.
13 
14     \tparam ResourceFactory    the type of the resource factory
15     \tparam ObservableFactory  the type of the observable factory
16 
17     \param  rf  the resource factory function that resturn the rxcpp::resource that is used as a resource by the observable factory
18     \param  of  the observable factory function to invoke for each observer that subscribes to the resulting observable
19 
20     \return  observable that makes an observable by the specified observable factory using the resource provided by the specified resource factory for each new observer that subscribes.
21 
22     \sample
23     \snippet scope.cpp scope sample
24     \snippet output.txt scope sample
25 */
26 
27 namespace rxcpp {
28 
29 namespace sources {
30 
31 namespace detail {
32 
33 template<class ResourceFactory, class ObservableFactory>
34 struct scope_traits
35 {
36     typedef rxu::decay_t<ResourceFactory> resource_factory_type;
37     typedef rxu::decay_t<ObservableFactory> observable_factory_type;
38     typedef decltype((*(resource_factory_type*)nullptr)()) resource_type;
39     typedef decltype((*(observable_factory_type*)nullptr)(resource_type())) collection_type;
40     typedef typename collection_type::value_type value_type;
41 
42     static_assert(is_subscription<resource_type>::value, "ResourceFactory must return a subscription");
43 };
44 
45 template<class ResourceFactory, class ObservableFactory>
46 struct scope : public source_base<rxu::value_type_t<scope_traits<ResourceFactory, ObservableFactory>>>
47 {
48     typedef scope_traits<ResourceFactory, ObservableFactory> traits;
49     typedef typename traits::resource_factory_type resource_factory_type;
50     typedef typename traits::observable_factory_type observable_factory_type;
51     typedef typename traits::resource_type resource_type;
52     typedef typename traits::value_type value_type;
53 
54     struct values
55     {
valuesrxcpp::sources::detail::scope::values56         values(resource_factory_type rf, observable_factory_type of)
57             : resource_factory(std::move(rf))
58             , observable_factory(std::move(of))
59         {
60         }
61         resource_factory_type resource_factory;
62         observable_factory_type observable_factory;
63     };
64     values initial;
65 
66 
scoperxcpp::sources::detail::scope67     scope(resource_factory_type rf, observable_factory_type of)
68         : initial(std::move(rf), std::move(of))
69     {
70     }
71 
72     template<class Subscriber>
on_subscriberxcpp::sources::detail::scope73     void on_subscribe(Subscriber o) const {
74 
75         struct state_type
76             : public std::enable_shared_from_this<state_type>
77             , public values
78         {
79             state_type(values i, Subscriber o)
80                 : values(i)
81                 , out(std::move(o))
82             {
83             }
84             Subscriber out;
85             rxu::detail::maybe<resource_type> resource;
86         };
87 
88         auto state = std::make_shared<state_type>(state_type(initial, std::move(o)));
89 
90         state->resource = on_exception(
91             [&](){return state->resource_factory(); },
92             state->out);
93         if (state->resource.empty()) {
94             return;
95         }
96         state->out.add(state->resource->get_subscription());
97 
98         auto selectedCollection = on_exception(
99             [state](){return state->observable_factory(state->resource.get()); },
100             state->out);
101         if (selectedCollection.empty()) {
102             return;
103         }
104 
105         selectedCollection->subscribe(state->out);
106     }
107 };
108 
109 }
110 
111 /*! @copydoc rx-scope.hpp
112  */
113 template<class ResourceFactory, class ObservableFactory>
scope(ResourceFactory rf,ObservableFactory of)114 auto scope(ResourceFactory rf, ObservableFactory of)
115     ->      observable<rxu::value_type_t<detail::scope_traits<ResourceFactory, ObservableFactory>>, detail::scope<ResourceFactory, ObservableFactory>> {
116     return  observable<rxu::value_type_t<detail::scope_traits<ResourceFactory, ObservableFactory>>, detail::scope<ResourceFactory, ObservableFactory>>(
117                                                                                                     detail::scope<ResourceFactory, ObservableFactory>(std::move(rf), std::move(of)));
118 }
119 
120 }
121 
122 }
123 
124 #endif
125