MIRA
RPCInvoker.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 by
3  * MetraLabs GmbH (MLAB), GERMANY
4  * and
5  * Neuroinformatics and Cognitive Robotics Labs (NICR) at TU Ilmenau, GERMANY
6  * All rights reserved.
7  *
8  * Contact: info@mira-project.org
9  *
10  * Commercial Usage:
11  * Licensees holding valid commercial licenses may use this file in
12  * accordance with the commercial license agreement provided with the
13  * software or, alternatively, in accordance with the terms contained in
14  * a written agreement between you and MLAB or NICR.
15  *
16  * GNU General Public License Usage:
17  * Alternatively, this file may be used under the terms of the GNU
18  * General Public License version 3.0 as published by the Free Software
19  * Foundation and appearing in the file LICENSE.GPL3 included in the
20  * packaging of this file. Please review the following information to
21  * ensure the GNU General Public License version 3.0 requirements will be
22  * met: http://www.gnu.org/copyleft/gpl.html.
23  * Alternatively you may (at your option) use any later version of the GNU
24  * General Public License if such license has been publicly approved by
25  * MLAB and NICR (or its successors, if any).
26  *
27  * IN NO EVENT SHALL "MLAB" OR "NICR" BE LIABLE TO ANY PARTY FOR DIRECT,
28  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
29  * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF "MLAB" OR
30  * "NICR" HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * "MLAB" AND "NICR" SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
33  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
34  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
35  * ON AN "AS IS" BASIS, AND "MLAB" AND "NICR" HAVE NO OBLIGATION TO
36  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR MODIFICATIONS.
37  */
38 
47 #ifndef _MIRA_RPCINVOKER_H__
48 #define _MIRA_RPCINVOKER_H__
49 
50 #include <functional>
51 #include <type_traits>
52 #ifndef Q_MOC_RUN
53 #include <boost/preprocessor/repetition.hpp>
54 #endif
55 
56 #include <error/Exception.h>
57 
58 #include <rpc/RPCError.h>
59 
60 namespace mira {
61 
63 
71 {
72 public:
73  virtual ~RPCInvoker() {}
74 };
75 
93 template<typename Backend>
94 class TRPCInvoker : public RPCInvoker
95 {
96 public:
100  virtual void invoke(typename Backend::ServerRequest& request,
101  typename Backend::ServerResponse& response) = 0;
102 };
103 
105 
106 namespace Private {
107 
108 template<typename P>
110 
111 template<typename Backend, typename T>
112 StrippedType<T> getFromRequest(typename Backend::ServerRequest& request)
113 {
114  StrippedType<T> p;
115  request.getParameter(p);
116  return p;
117 }
118 
119 // helper function to avoid code duplication. must only be called in a catch()-clause!
120 template<typename Response>
121 void throwRPCException(Response& response)
122 {
123  try {
124  throw;
125  }
126  catch (SerializableException& ex) {
127  response.returnException(RPC_EXCEPTION_IN_CALL, ex);
128  return;
129  }
130  catch (Exception& ex) {
131  response.returnException(RPC_EXCEPTION_IN_CALL, ex.what(), ex.callStack());
132  return;
133  }
134  catch (std::exception& ex) {
135  response.returnException(RPC_EXCEPTION_IN_CALL, ex.what());
136  return;
137  }
138  catch (...) {
139  response.returnException(RPC_EXCEPTION_IN_CALL, "Unknown exception");
140  return;
141  }
142 }
143 
144 // The helper is required since we have methods with and without return value.
145 // For non-void return types it serializes the return value. There is a specialized version for a return type
146 // of void which just calls the method without taking care of the return value (which is just void).
147 template<typename R>
149 {
150  template<typename Backend, typename Fn, typename... ARGS>
151  static void invoke(typename Backend::ServerResponse& response, const Fn& fn, ARGS&&... parameters)
152  {
153  try {
154  response.template returnResult<R>(fn(std::forward<ARGS>(parameters)...));
155  }
156  catch (...) {
157  Private::throwRPCException(response);
158  }
159  }
160 };
161 
162 // Specialization for return type "void"
163 template<>
164 struct RPCInvokeHelper<void>
165 {
166  template<typename Backend, typename Fn, typename... ARGS>
167  static void invoke(typename Backend::ServerResponse& response, const Fn& fn, ARGS&&... parameters)
168  {
169  try {
170  fn(std::forward<ARGS>(parameters)...);
171  }
172  catch (...) {
173  Private::throwRPCException(response);
174  return;
175  }
176  response.returnVoid();
177  }
178 };
179 
180 // The helper is required since we have methods with and without return value.
181 // For non-void return types it serializes the return value. There is a specialized version for a return type
182 // of void which just calls the method without taking care of the return value (which is just void).
183 template<typename R>
185 {
186  template<typename Backend, typename MemFn, typename Class, typename... ARGS>
187  static void invoke(typename Backend::ServerResponse& response, const MemFn& fn, Class* obj,
188  ARGS&&... parameters)
189  {
190  try {
191  response.template returnResult<R>(fn(obj, std::forward<ARGS>(parameters)...));
192  }
193  catch (...) {
194  Private::throwRPCException(response);
195  }
196  }
197 };
198 
199 // Specialization for return type "void"
200 template<>
201 struct RPCInvokeHelperMem<void>
202 {
203  template<typename Backend, typename MemFn, typename Class, typename... ARGS>
204  static void invoke(typename Backend::ServerResponse& response, const MemFn& fn, Class* obj,
205  ARGS&&... parameters)
206  {
207  try {
208  fn(obj, std::forward<ARGS>(parameters)...);
209  }
210  catch (...) {
211  Private::throwRPCException(response);
212  return;
213  }
214  response.returnVoid();
215  }
216 };
217 
218 template<typename Backend, typename R, typename... ARGS>
219 struct ConcreteRPCInvoker : public TRPCInvoker<Backend>
220 {
221  template<class P>
222  static Private::StrippedType<P> getParameter(typename Backend::ServerRequest& request)
223  {
224  return Private::getFromRequest<Backend, P>(request);
225  }
226 
227  typedef std::function<R(ARGS...)> Fn;
228  ConcreteRPCInvoker(const Fn& f) : fn(f) {}
229  ConcreteRPCInvoker(Fn&& f) : fn(std::move(f)) {}
230  void invoke(typename Backend::ServerRequest& request, typename Backend::ServerResponse& response) final
231  {
232  parseArguments<ARGS...>(request, response);
233  }
234 
235  // extract parameters recursively:
236  // pack of (explicit) template parameters shrinks while pack of function parameters grows
237  template<typename Head, typename... Tail, typename... Args>
238  void parseArguments(typename Backend::ServerRequest& request, typename Backend::ServerResponse& response,
239  Args&&... args)
240  {
241  parseArguments<Tail...>(request, response, std::forward<Args>(args)..., getParameter<Head>(request));
242  }
243 
244  // stop recursing when all parameters have been extracted from the request
245  template<typename... Ignore> // make this a template method (but not an explicit specialization!)
246  void parseArguments(typename Backend::ServerRequest& request, typename Backend::ServerResponse& response,
247  Private::StrippedType<ARGS>&&... args)
248  {
249  Private::RPCInvokeHelper<R>::template invoke<Backend>(response, fn, std::move(args)...);
250  }
251 
253 };
254 
255 template<typename Backend, typename MemFn, typename Class, typename... ARGS>
256 struct ConcreteRPCInvoker_memfn : public TRPCInvoker<Backend>
257 {
258  template<class P>
259  static Private::StrippedType<P> getParameter(typename Backend::ServerRequest& request)
260  {
261  return Private::getFromRequest<Backend, P>(request);
262  }
263 
264  ConcreteRPCInvoker_memfn(const MemFn& f, Class* obj) : fn(f), This(obj) {}
265  ConcreteRPCInvoker_memfn(MemFn&& f, Class* obj) : fn(std::move(f)), This(obj) {}
266  void invoke(typename Backend::ServerRequest& request, typename Backend::ServerResponse& response) final
267  {
268  parseArguments<ARGS...>(request, response);
269  }
270 
271  // extract parameters recursively:
272  // pack of (explicit) template parameters shrinks while pack of function parameters grows
273  template<typename Head, typename... Tail, typename... Args>
274  void parseArguments(typename Backend::ServerRequest& request, typename Backend::ServerResponse& response,
275  Args&&... args)
276  {
277  parseArguments<Tail...>(request, response, std::forward<Args>(args)..., getParameter<Head>(request));
278  }
279 
280  // stop recursing when all parameters have been extracted from the request
281  template<typename... Ignore> // make this a template method (but not an explicit specialization!)
282  void parseArguments(typename Backend::ServerRequest& request, typename Backend::ServerResponse& response,
283  Private::StrippedType<ARGS>&&... args)
284  {
286  response, fn, This, std::move(args)...);
287  }
288 
289  MemFn fn;
291 };
292 
293 } // namespace Private
294 
296 
297 template<typename Backend, typename R, typename... ARGS, typename Fn>
298 Private::ConcreteRPCInvoker<Backend, R, ARGS...>* make_RPCInvoker(Fn&& f)
299 {
300  return new Private::ConcreteRPCInvoker<Backend, R, ARGS...>(std::forward<Fn>(f));
301 }
302 
303 template<typename Backend, typename... ARGS, typename MemFn, typename Class>
304 Private::ConcreteRPCInvoker_memfn<Backend, MemFn, Class, ARGS...>* make_RPCInvoker(MemFn&& f, Class* obj)
305 {
306  return new Private::ConcreteRPCInvoker_memfn<Backend, MemFn, Class, ARGS...>(std::forward<MemFn>(f), obj);
307 }
308 
310 
311 } // namespace mira
312 
313 #endif /* _MIRA_RPCINVOKER_H_ */
Definition: RPCInvoker.h:148
static void invoke(typename Backend::ServerResponse &response, const MemFn &fn, Class *obj, ARGS &&... parameters)
Definition: RPCInvoker.h:187
void parseArguments(typename Backend::ServerRequest &request, typename Backend::ServerResponse &response, Private::StrippedType< ARGS > &&... args)
Definition: RPCInvoker.h:282
ConcreteRPCInvoker(const Fn &f)
Definition: RPCInvoker.h:228
Definition: RPCInvoker.h:184
Fn fn
Definition: RPCInvoker.h:252
specialize cv::DataType for our ImgPixel and inherit from cv::DataType<Vec>
Definition: IOService.h:67
Error codes for reasons of errors/exceptions while processing an rpc call.
Invoker that is used to invoke an RPC method call for a special backend.
Definition: RPCInvoker.h:94
Class object which supports some kind of class reflection.
Definition: Class.h:97
STL namespace.
void invoke(typename Backend::ServerRequest &request, typename Backend::ServerResponse &response) final
object is pointer to service object whose method is called
Definition: RPCInvoker.h:230
Class * This
Definition: RPCInvoker.h:290
void parseArguments(typename Backend::ServerRequest &request, typename Backend::ServerResponse &response, Args &&... args)
Definition: RPCInvoker.h:274
typename std::remove_const< typename std::remove_reference< P >::type >::type StrippedType
Definition: RPCInvoker.h:109
ConcreteRPCInvoker(Fn &&f)
Definition: RPCInvoker.h:229
An exception has occurred within the method that was called.
Definition: RPCError.h:69
ConcreteRPCInvoker_memfn(const MemFn &f, Class *obj)
Definition: RPCInvoker.h:264
PropertyHint type(const std::string &t)
Sets the attribute "type" to the specified value.
Definition: PropertyHint.h:295
Definition: RPCInvoker.h:256
std::function< R(ARGS...)> Fn
Definition: RPCInvoker.h:227
static void invoke(typename Backend::ServerResponse &response, const Fn &fn, ARGS &&... parameters)
Definition: RPCInvoker.h:167
const CallStack & callStack() const
Returns the state of the callstack at the moment when the exception was thrown.
Definition: Exception.h:252
static void invoke(typename Backend::ServerResponse &response, const Fn &fn, ARGS &&... parameters)
Definition: RPCInvoker.h:151
virtual ~RPCInvoker()
Definition: RPCInvoker.h:73
Base of all TRPCInvoker classes which are templates to support different RPC backends.
Definition: RPCInvoker.h:70
Base class for exceptions.
Definition: Exception.h:194
MemFn fn
Definition: RPCInvoker.h:289
static Private::StrippedType< P > getParameter(typename Backend::ServerRequest &request)
Definition: RPCInvoker.h:259
static Private::StrippedType< P > getParameter(typename Backend::ServerRequest &request)
Definition: RPCInvoker.h:222
Definition: RPCInvoker.h:219
virtual void invoke(typename Backend::ServerRequest &request, typename Backend::ServerResponse &response)=0
object is pointer to service object whose method is called
void parseArguments(typename Backend::ServerRequest &request, typename Backend::ServerResponse &response, Args &&... args)
Definition: RPCInvoker.h:238
void parseArguments(typename Backend::ServerRequest &request, typename Backend::ServerResponse &response, Private::StrippedType< ARGS > &&... args)
Definition: RPCInvoker.h:246
ConcreteRPCInvoker_memfn(MemFn &&f, Class *obj)
Definition: RPCInvoker.h:265
virtual const char * what() const MIRA_NOEXCEPT_OR_NOTHROW
Returns the text of exception containing the information given in MIRA_THROW and MIRA_RETHROW as well...
void throwRPCException(Response &response)
Definition: RPCInvoker.h:121
StrippedType< T > getFromRequest(typename Backend::ServerRequest &request)
Definition: RPCInvoker.h:112
Private::ConcreteRPCInvoker< Backend, R, ARGS... > * make_RPCInvoker(Fn &&f)
Definition: RPCInvoker.h:298
Exception base class.
Definition: Exceptions.h:85
void invoke(typename Backend::ServerRequest &request, typename Backend::ServerResponse &response) final
object is pointer to service object whose method is called
Definition: RPCInvoker.h:266
static void invoke(typename Backend::ServerResponse &response, const MemFn &fn, Class *obj, ARGS &&... parameters)
Definition: RPCInvoker.h:204