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 
53 #include <error/Exception.h>
54 
55 #include <rpc/RPCError.h>
56 
57 namespace mira {
58 
60 
68 {
69 public:
70  virtual ~RPCInvoker() {}
71 };
72 
90 template<typename Backend>
91 class TRPCInvoker : public RPCInvoker
92 {
93 public:
97  virtual void invoke(typename Backend::ServerRequest& request,
98  typename Backend::ServerResponse& response) = 0;
99 };
100 
102 
103 namespace Private {
104 
105 template<typename P>
107 
108 template<typename Backend, typename T>
109 StrippedType<T> getFromRequest(typename Backend::ServerRequest& request)
110 {
111  StrippedType<T> p;
112  request.getParameter(p);
113  return p;
114 }
115 
116 // helper function to avoid code duplication. must only be called in a catch()-clause!
117 template<typename Response>
118 void throwRPCException(Response& response)
119 {
120  try {
121  throw;
122  }
123  catch (SerializableException& ex) {
124  response.returnException(RPC_EXCEPTION_IN_CALL, ex);
125  return;
126  }
127  catch (Exception& ex) {
128  response.returnException(RPC_EXCEPTION_IN_CALL, ex.what(), ex.callStack());
129  return;
130  }
131  catch (std::exception& ex) {
132  response.returnException(RPC_EXCEPTION_IN_CALL, ex.what());
133  return;
134  }
135  catch (...) {
136  response.returnException(RPC_EXCEPTION_IN_CALL, "Unknown exception");
137  return;
138  }
139 }
140 
141 // The helper is required since we have methods with and without return value.
142 // For non-void return types it serializes the return value. There is a specialized version for a return type
143 // of void which just calls the method without taking care of the return value (which is just void).
144 template<typename R>
146 {
147  template<typename Backend, typename Fn, typename... ARGS>
148  static void invoke(typename Backend::ServerResponse& response, const Fn& fn, ARGS&&... parameters)
149  {
150  try {
151  response.template returnResult<R>(fn(std::forward<ARGS>(parameters)...));
152  }
153  catch (...) {
154  Private::throwRPCException(response);
155  }
156  }
157 };
158 
159 // Specialization for return type "void"
160 template<>
161 struct RPCInvokeHelper<void>
162 {
163  template<typename Backend, typename Fn, typename... ARGS>
164  static void invoke(typename Backend::ServerResponse& response, const Fn& fn, ARGS&&... parameters)
165  {
166  try {
167  fn(std::forward<ARGS>(parameters)...);
168  }
169  catch (...) {
170  Private::throwRPCException(response);
171  return;
172  }
173  response.returnVoid();
174  }
175 };
176 
177 template<typename MemFn, typename Class>
179 {
180 public:
181  MemberInvoker(const MemFn& func, Class* ptr) : fn{func}, This{ptr} {};
182  MemberInvoker(MemFn&& func, Class* ptr) : fn{std::move(func)}, This{ptr} {};
183 
184  typedef typename MemFn::result_type ResultType;
185 
186  template<typename... ARGS>
187  ResultType operator()(ARGS&&... args) const
188  {
189  return fn(This, std::forward<ARGS>(args)...);
190  }
191 
192 private:
193  MemFn fn;
194  Class* This;
195 };
196 
197 template<typename Backend, typename Function, typename R, typename... ARGS>
198 struct ConcreteRPCInvoker : public TRPCInvoker<Backend>
199 {
200  template<class P>
201  static Private::StrippedType<P> getParameter(typename Backend::ServerRequest& request)
202  {
203  return Private::getFromRequest<Backend, P>(request);
204  }
205 
206  ConcreteRPCInvoker(const Function& f) : fn(f) {}
207  ConcreteRPCInvoker(Function&& f) : fn(std::move(f)) {}
208  void invoke(typename Backend::ServerRequest& request, typename Backend::ServerResponse& response) final
209  {
210  parseArguments<ARGS...>(request, response);
211  }
212 
213  // extract parameters recursively:
214  // pack of (explicit) template parameters shrinks while pack of function parameters grows
215  template<typename Head, typename... Tail, typename... Args>
216  void parseArguments(typename Backend::ServerRequest& request, typename Backend::ServerResponse& response,
217  Args&&... args)
218  {
219  parseArguments<Tail...>(request, response, std::forward<Args>(args)..., getParameter<Head>(request));
220  }
221 
222  // stop recursing when all parameters have been extracted from the request
223  template<typename... Ignore> // make this a template method (but not an explicit specialization!)
224  void parseArguments(typename Backend::ServerRequest& request, typename Backend::ServerResponse& response,
225  Private::StrippedType<ARGS>&&... args)
226  {
227  Private::RPCInvokeHelper<R>::template invoke<Backend>(response, fn, std::move(args)...);
228  }
229 
230  Function fn;
231 };
232 
233 } // namespace Private
234 
236 
237 template<typename Backend, typename R, typename... ARGS, typename Fn>
239 {
241  std::forward<Fn>(f));
242 }
243 
245 
246 } // namespace mira
247 
248 #endif /* _MIRA_RPCINVOKER_H_ */
Function fn
Definition: RPCInvoker.h:230
Definition: RPCInvoker.h:145
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:182
ConcreteRPCInvoker(const Function &f)
Definition: RPCInvoker.h:206
Invoker that is used to invoke an RPC method call for a special backend.
Definition: RPCInvoker.h:91
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:208
typename std::remove_const< typename std::remove_reference< P >::type >::type StrippedType
Definition: RPCInvoker.h:106
Definition: RPCInvoker.h:178
Private::ConcreteRPCInvoker< Backend, typename std::decay< Fn >::type, R, ARGS... > * make_RPCInvoker(Fn &&f)
Definition: RPCInvoker.h:238
MemberInvoker(const MemFn &func, Class *ptr)
Definition: RPCInvoker.h:181
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:164
const CallStack & callStack() const
Returns the state of the callstack at the moment when the exception was thrown.
Definition: Exception.h:253
static void invoke(typename Backend::ServerResponse &response, const Fn &fn, ARGS &&... parameters)
Definition: RPCInvoker.h:148
virtual ~RPCInvoker()
Definition: RPCInvoker.h:70
Base of all TRPCInvoker classes which are templates to support different RPC backends.
Definition: RPCInvoker.h:67
Base class for exceptions.
Definition: Exception.h:195
ConcreteRPCInvoker(Function &&f)
Definition: RPCInvoker.h:207
ResultType operator()(ARGS &&... args) const
Definition: RPCInvoker.h:187
static Private::StrippedType< P > getParameter(typename Backend::ServerRequest &request)
Definition: RPCInvoker.h:201
Definition: RPCInvoker.h:198
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:216
void parseArguments(typename Backend::ServerRequest &request, typename Backend::ServerResponse &response, Private::StrippedType< ARGS > &&... args)
Definition: RPCInvoker.h:224
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:118
StrippedType< T > getFromRequest(typename Backend::ServerRequest &request)
Definition: RPCInvoker.h:109
Exception base class.
Definition: Exceptions.h:85