Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
method.hpp
Go to the documentation of this file.
1#pragma once
2
3//clashes with BOOST PP and Some Applications
4#pragma push_macro("N")
5#undef N
6
7#include <boost/signals2.hpp>
8#include <boost/exception/diagnostic_information.hpp>
9
10namespace appbase {
11
12 using erased_method_ptr = std::unique_ptr<void, void(*)(void*)>;
13
18 template<typename FunctionSig>
20
21 template<typename Ret, typename ... Args>
22 struct first_success_policy<Ret(Args...)> {
23 using result_type = Ret;
24
35 template<typename InputIterator>
36 Ret operator()(InputIterator first, InputIterator last) {
37 std::string err;
38 while (first != last) {
39 try {
40 return *first; // de-referencing the iterator causes the provider to run
41 } catch (...) {
42 if (!err.empty()) {
43 err += "\",\"";
44 }
45
46 err += boost::current_exception_diagnostic_information();
47 }
48
49 ++first;
50 }
51
52 throw std::length_error(std::string("No Result Available, All providers returned exceptions[") + err + "]");
53 }
54 };
55
56 template<typename ... Args>
57 struct first_success_policy<void(Args...)> {
58 using result_type = void;
59
70 template<typename InputIterator>
71 void operator()(InputIterator first, InputIterator last) {
72 std::string err;
73
74 while (first != last) {
75 try {
76 *first; // de-referencing the iterator causes the provider to run
77 } catch (...) {
78 if (!err.empty()) {
79 err += "\",\"";
80 }
81
82 err += boost::current_exception_diagnostic_information();
83 }
84
85 ++first;
86 }
87
88 throw std::length_error(std::string("No Result Available, All providers returned exceptions[") + err + "]");
89 }
90 };
91
92
96 template<typename FunctionSig>
98
99 template<typename Ret, typename ... Args>
100 struct first_provider_policy<Ret(Args...)> {
101 using result_type = Ret;
102
112 template<typename InputIterator>
113 Ret operator()(InputIterator first, InputIterator) {
114 return *first;
115 }
116 };
117
118 template<typename ... Args>
119 struct first_provider_policy<void(Args...)> {
120 using result_type = void;
121
131 template<typename InputIterator>
132 void operator()(InputIterator first, InputIterator) {
133 *first;
134 }
135 };
136
137 namespace impl {
138 template<typename FunctionSig, typename DispatchPolicy>
140
141 template<typename Ret, typename ...Args, typename DispatchPolicy>
142 class method_caller<Ret(Args...), DispatchPolicy> {
143 public:
144 using signal_type = boost::signals2::signal<Ret(Args...), DispatchPolicy>;
145 using result_type = Ret;
146
149
155 Ret operator()(Args&&... args)
156 {
157 return _signal(std::forward<Args>(args)...);
158 }
159
161 };
162
163 template<typename ...Args, typename DispatchPolicy>
164 class method_caller<void(Args...), DispatchPolicy> {
165 public:
166 using signal_type = boost::signals2::signal<void(Args...), DispatchPolicy>;
167 using result_type = void;
168
171
177 void operator()(Args&&... args)
178 {
179 _signal(std::forward<Args>(args)...);
180 }
181
183 };
184 }
185
196 template<typename FunctionSig, typename DispatchPolicy>
197 class method final : public impl::method_caller<FunctionSig,DispatchPolicy> {
198 public:
203 class handle {
204 public:
206 unregister();
207 }
208
213 void unregister() {
214 if (_handle.connected()) {
215 _handle.disconnect();
216 }
217 }
218
219 // This handle can be constructed and moved
220 handle() = default;
221 handle(handle&&) = default;
222 handle& operator= (handle&& rhs) = default;
223
224 // dont allow copying since this protects the resource
225 handle(const handle& ) = delete;
226 handle& operator= (const handle& ) = delete;
227
228 private:
229 using handle_type = boost::signals2::connection;
230 handle_type _handle;
231
238 handle(handle_type&& _handle)
239 :_handle(std::move(_handle))
240 {}
241
242 friend class method;
243 };
244
252 template<typename T>
253 handle register_provider(T provider, int priority = 0) {
254 return handle(this->_signal.connect(priority, provider));
255 }
256
257 protected:
258 method() = default;
259 virtual ~method() = default;
260
267 static void deleter(void* erased_method_ptr) {
268 auto ptr = reinterpret_cast<method*>(erased_method_ptr);
269 delete ptr;
270 }
271
279 return reinterpret_cast<method*>(ptr.get());
280 }
281
287 return erased_method_ptr(new method(), &deleter);
288 }
289
291 };
292
293
300 template< typename Tag, typename FunctionSig, template <typename> class DispatchPolicy = first_success_policy>
305
306 template <typename Tag, typename FunctionSig, template <typename> class DispatchPolicy>
308
309 std::false_type is_method_decl_impl(...);
310
311 template <typename T>
312 using is_method_decl = decltype(is_method_decl_impl(std::declval<T*>()));
313
314
315}
316
317#pragma pop_macro("N")
318
boost::signals2::signal< Ret(Args...), DispatchPolicy > signal_type
Definition method.hpp:144
boost::signals2::signal< void(Args...), DispatchPolicy > signal_type
Definition method.hpp:166
handle(handle &&)=default
handle & operator=(handle &&rhs)=default
handle(const handle &)=delete
method()=default
static erased_method_ptr make_unique()
Definition method.hpp:286
static method * get_method(erased_method_ptr &ptr)
Definition method.hpp:278
handle register_provider(T provider, int priority=0)
Definition method.hpp:253
static void deleter(void *erased_method_ptr)
Definition method.hpp:267
virtual ~method()=default
std::true_type is_method_decl_impl(const method_decl< Tag, FunctionSig, DispatchPolicy > *)
decltype(is_method_decl_impl(std::declval< T * >())) is_method_decl
Definition method.hpp:312
std::unique_ptr< void, void(*)(void *)> erased_method_ptr
Definition method.hpp:12
Definition name.hpp:106
#define T(meth, val, expected)
Ret operator()(InputIterator first, InputIterator)
Definition method.hpp:113
void operator()(InputIterator first, InputIterator)
Definition method.hpp:132
Ret operator()(InputIterator first, InputIterator last)
Definition method.hpp:36
void operator()(InputIterator first, InputIterator last)
Definition method.hpp:71