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 template<typename MemFn, typename Class>
182 {
183 public:
184  MemberInvoker(const MemFn& func, Class* ptr) : fn{func}, This{ptr} {};
185  MemberInvoker(MemFn&& func, Class* ptr) : fn{std::move(func)}, This{ptr} {};
186 
187  typedef typename MemFn::result_type ResultType;
188 
189  template<typename... ARGS>
190  ResultType operator()(ARGS&&... args) const
191  {
192  return fn(This, std::forward<ARGS>(args)...);
193  }
194 
195 private:
196  MemFn fn;
197  Class* This;
198 };
199 
200 template<typename Backend, typename Function, typename R, typename... ARGS>
201 struct ConcreteRPCInvoker : public TRPCInvoker<Backend>
202 {
203  template<class P>
204  static Private::StrippedType<P> getParameter(typename Backend::ServerRequest& request)
205  {
206  return Private::getFromRequest<Backend, P>(request);
207  }
208 
209  ConcreteRPCInvoker(const Function& f) : fn(f) {}
210  ConcreteRPCInvoker(Function&& f) : fn(std::move(f)) {}
211  void invoke(typename Backend::ServerRequest& request, typename Backend::ServerResponse& response) final
212  {
213  parseArguments<ARGS...>(request, response);
214  }
215 
216  // extract parameters recursively:
217  // pack of (explicit) template parameters shrinks while pack of function parameters grows
218  template<typename Head, typename... Tail, typename... Args>
219  void parseArguments(typename Backend::ServerRequest& request, typename Backend::ServerResponse& response,
220  Args&&... args)
221  {
222  parseArguments<Tail...>(request, response, std::forward<Args>(args)..., getParameter<Head>(request));
223  }
224 
225  // stop recursing when all parameters have been extracted from the request
226  template<typename... Ignore> // make this a template method (but not an explicit specialization!)
227  void parseArguments(typename Backend::ServerRequest& request, typename Backend::ServerResponse& response,
228  Private::StrippedType<ARGS>&&... args)
229  {
230  Private::RPCInvokeHelper<R>::template invoke<Backend>(response, fn, std::move(args)...);
231  }
232 
233  Function fn;
234 };
235 
236 } // namespace Private
237 
239 
240 template<typename Backend, typename R, typename... ARGS, typename Fn>
242 {
244  std::forward<Fn>(f));
245 }
246 
248 
249 } // namespace mira
250 
251 #endif /* _MIRA_RPCINVOKER_H_ */
Function fn
Definition: RPCInvoker.h:233
Definition: RPCInvoker.h:148
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.
MemFn::result_type ResultType
Definition: RPCInvoker.h:185
ConcreteRPCInvoker(const Function &f)
Definition: RPCInvoker.h:209
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:211
typename std::remove_const< typename std::remove_reference< P >::type >::type StrippedType
Definition: RPCInvoker.h:109
Definition: RPCInvoker.h:181
Private::ConcreteRPCInvoker< Backend, typename std::decay< Fn >::type, R, ARGS... > * make_RPCInvoker(Fn &&f)
Definition: RPCInvoker.h:241
MemberInvoker(const MemFn &func, Class *ptr)
Definition: RPCInvoker.h:184
An exception has occurred within the method that was called.
Definition: RPCError.h:69
PropertyHint type(const std::string &t)
Sets the attribute "type" to the specified value.
Definition: PropertyHint.h:295
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:257
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:199
ConcreteRPCInvoker(Function &&f)
Definition: RPCInvoker.h:210
ResultType operator()(ARGS &&... args) const
Definition: RPCInvoker.h:190
static Private::StrippedType< P > getParameter(typename Backend::ServerRequest &request)
Definition: RPCInvoker.h:204
Definition: RPCInvoker.h:201
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:219
void parseArguments(typename Backend::ServerRequest &request, typename Backend::ServerResponse &response, Private::StrippedType< ARGS > &&... args)
Definition: RPCInvoker.h:227
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
Exception base class.
Definition: Exceptions.h:85