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