]> git.sesse.net Git - casparcg/blob - core/monitor/monitor.h
6c9f54b197f9d5ac2d9868f34f7c7626ca819665
[casparcg] / core / monitor / monitor.h
1 #pragma once\r
2 \r
3 #include <common/reactive.h>\r
4 \r
5 #include <functional>\r
6 #include <memory>\r
7 #include <ostream>\r
8 #include <string>\r
9 #include <type_traits>\r
10 #include <vector>\r
11 \r
12 #include <boost/variant.hpp>\r
13 #include <boost/lexical_cast.hpp>\r
14 #include <boost/chrono.hpp>\r
15 \r
16 #include <tbb/cache_aligned_allocator.h>\r
17 \r
18 namespace boost {\r
19 namespace detail { namespace variant {\r
20 \r
21 template <>\r
22 struct has_nothrow_move<std::string>\r
23 : mpl::true_\r
24 {\r
25 };\r
26   \r
27 template <>\r
28 struct has_nothrow_move<std::vector<int8_t>>\r
29 : mpl::true_\r
30 {\r
31 };\r
32 \r
33 template <>\r
34 struct has_nothrow_move<boost::chrono::duration<double, boost::ratio<1, 1>>>\r
35 : mpl::true_\r
36 {\r
37 };\r
38 \r
39 }}}\r
40 \r
41 namespace caspar { namespace monitor {\r
42         \r
43 // path\r
44 \r
45 class path sealed\r
46 {\r
47 public: \r
48 \r
49         // Static Members\r
50 \r
51         // Constructors\r
52 \r
53         path();         \r
54         path(const char* path);\r
55         path(std::string path);\r
56 \r
57         path(const path& other);        \r
58         path(path&& other);\r
59                 \r
60         // Methods\r
61 \r
62         path& operator=(path other);\r
63         path& operator%=(path other);\r
64 \r
65         template<typename T>\r
66         typename std::enable_if<!std::is_same<typename std::decay<T>::type, path>::value, path&>::type operator%=(T&& value)\r
67         {\r
68                 auto str = boost::lexical_cast<std::string>(std::forward<T>(value));\r
69 \r
70                 if(!str.empty())\r
71                         str_ += (str.front() != '/' ? "/" : "") + std::move(str);\r
72 \r
73                 return *this;\r
74         }\r
75         \r
76         path& operator%=(const char* value)\r
77         {\r
78                 return *this %= std::string(value);\r
79         }\r
80 \r
81         void swap(path& other);\r
82 \r
83         // Properties\r
84 \r
85         const std::string& str() const; \r
86         bool empty() const;\r
87 private:\r
88         std::string str_;\r
89 };\r
90 \r
91 template<typename T>\r
92 path operator%(path path, T&& value)\r
93 {       \r
94         return std::move(path %= std::forward<T>(value));\r
95 }\r
96 \r
97 std::ostream& operator<<(std::ostream& o, const path& p);\r
98 \r
99 // param\r
100 \r
101 typedef boost::chrono::duration<double, boost::ratio<1, 1>> duration;\r
102 \r
103 typedef boost::variant<bool, int32_t, int64_t, float, double, std::string, std::wstring, std::vector<int8_t>, duration> param;\r
104 \r
105 std::ostream& operator<<(std::ostream& o, const param& p);\r
106 \r
107 // event\r
108 \r
109 class event sealed\r
110 {       \r
111 public: \r
112         \r
113         // Static Members\r
114 \r
115         typedef std::vector<param, tbb::cache_aligned_allocator<param>> params_t;\r
116 \r
117         // Constructors\r
118 \r
119         event(path path);       \r
120         event(path path, params_t params);                                      \r
121         event(const event& other);\r
122         event(event&& other);\r
123 \r
124         // Methods\r
125 \r
126         event& operator=(event other);\r
127 \r
128         void swap(event& other);\r
129                 \r
130         template<typename T>\r
131         event& operator%(T&& value)\r
132         {\r
133                 params_.push_back(std::forward<T>(value));\r
134                 return *this;\r
135         }\r
136         \r
137         event propagate(path path) const;\r
138 \r
139         // Properties\r
140 \r
141         const path&             path() const;\r
142         const params_t& params() const;\r
143 private:\r
144         monitor::path   path_;\r
145         params_t                params_;\r
146 };\r
147 \r
148 std::ostream& operator<<(std::ostream& o, const event& e);\r
149 \r
150 // reactive\r
151 \r
152 typedef reactive::observable<monitor::event>    observable;\r
153 typedef reactive::observer<monitor::event>              observer;\r
154 typedef reactive::subject<monitor::event>               subject;\r
155         \r
156 class basic_subject sealed : public reactive::subject<monitor::event>\r
157 {           \r
158         basic_subject(const basic_subject&);\r
159         basic_subject& operator=(const basic_subject&);\r
160         \r
161         class impl : public observer\r
162         {\r
163         public:\r
164                 impl(monitor::path path = monitor::path())\r
165                         : impl_()\r
166                         , path_(std::move(path))\r
167                 {\r
168                 }\r
169 \r
170                 impl(impl&& other)\r
171                         : impl_(std::move(other.impl_))\r
172                         , path_(std::move(other.path_))\r
173                 {               \r
174                 }\r
175 \r
176                 impl& operator=(impl&& other)\r
177                 {\r
178                         impl_ = std::move(other.impl_);         \r
179                         path_ = std::move(other.path_);\r
180                 }\r
181                                                         \r
182                 void on_next(const monitor::event& e) override\r
183                 {                               \r
184                         impl_.on_next(path_.empty() ? e : e.propagate(path_));\r
185                 }\r
186 \r
187                 void subscribe(const observer_ptr& o)\r
188                 {                               \r
189                         impl_.subscribe(o);\r
190                 }\r
191 \r
192                 void unsubscribe(const observer_ptr& o)\r
193                 {\r
194                         impl_.unsubscribe(o);\r
195                 }\r
196                                 \r
197         private:\r
198                 reactive::basic_subject_impl<monitor::event>    impl_;          \r
199                 monitor::path                                                                   path_;\r
200         };\r
201 \r
202 public:         \r
203 \r
204         // Static Members\r
205 \r
206         // Constructors\r
207 \r
208         basic_subject(monitor::path path = monitor::path())\r
209                 : impl_(std::make_shared<impl>(std::move(path)))\r
210 \r
211         {\r
212         }\r
213                 \r
214         basic_subject(basic_subject&& other)\r
215                 : impl_(std::move(other.impl_))\r
216         {\r
217         }\r
218         \r
219         // Methods\r
220 \r
221         basic_subject& operator=(basic_subject&& other)\r
222         {\r
223                 impl_ = std::move(other.impl_);\r
224         }\r
225 \r
226         operator std::weak_ptr<observer>()\r
227         {\r
228                 return impl_;\r
229         }\r
230 \r
231         // observable\r
232         \r
233         void subscribe(const observer_ptr& o) override\r
234         {                               \r
235                 impl_->subscribe(o);\r
236         }\r
237 \r
238         void unsubscribe(const observer_ptr& o) override\r
239         {\r
240                 impl_->unsubscribe(o);\r
241         }\r
242 \r
243         // observer\r
244                                 \r
245         void on_next(const monitor::event& e) override\r
246         {                               \r
247                 impl_->on_next(e);\r
248         }\r
249 \r
250         // Properties\r
251 \r
252 private:\r
253         std::shared_ptr<impl> impl_;\r
254 };\r
255 \r
256 inline subject& operator<<(subject& s, const event& e)\r
257 {\r
258         s.on_next(e);\r
259         return s;\r
260 }\r
261 \r
262 }}