MIRA
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RPCFuture.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_RPCFUTURE_H_
48 #define _MIRA_RPCFUTURE_H_
49 
50 #ifndef Q_MOC_RUN
51 #include <boost/noncopyable.hpp>
52 #include <boost/thread/future.hpp>
53 #endif
54 
55 #include <rpc/AbstractRPCClient.h>
56 #include <rpc/JSONRPCResponse.h>
57 #include <rpc/RPCError.h>
58 
59 namespace mira {
60 
62 
67 template <typename R>
68 class RPCFutureCommon : boost::noncopyable
69 {
70 public:
71 
72  RPCFutureCommon() : mClient(NULL), mCallId("") {}
73 
74  RPCFutureCommon(AbstractRPCClient* client, const std::string& callId) :
75  mClient(client), mCallId(callId) {}
76 
78  {
79  // remove call upon destruction of this future
80  if(mClient!=NULL)
82  }
83 
84 public:
85 
87  const std::string& callId() { return mCallId; }
88 
89  // delegate to boost future
90 
92  bool isReady() const { return mFuture.is_ready(); }
93 
98  bool hasException() const { return mFuture.has_exception(); }
99 
104  bool hasValue() const { return mFuture.has_value(); }
105 
111  void wait() const { mFuture.wait(); }
112 
121  template<typename Duration>
122  bool timedWait(Duration const& relTime) const {
123  return mFuture.timed_wait(relTime);
124  }
125 
133  bool timedWaitUntil(boost::system_time const& absTime) const {
134  return mFuture.timed_wait_until(absTime);
135  }
136 
138  void swap(RPCFutureCommon<R>& other) {
139  mFuture.swap(other.mFuture);
140  std::swap(mClient, other.mClient);
141  std::swap(mCallId, other.mCallId);
142  }
143 
144 
145 protected:
147  std::string mCallId;
148  boost::unique_future<R> mFuture;
149 };
150 
152 
172 template <typename R>
173 class RPCFuture : public RPCFutureCommon<R>
174 {
175 public:
177 
179  RPCFuture(boost::unique_future<R> other, AbstractRPCClient* client,
180  const std::string& callId) :
181  RPCFutureCommon<R>(client, callId)
182  {
183  this->mFuture.swap(other);
184  }
185 
187  RPCFuture(RPCFuture&& other) {
188  this->swap(other);
189  }
190 
193  this->swap(other);
194  return *this;
195  }
196 
197 public:
198 
200 
201 #if BOOST_VERSION / 100 % 1000 > 56
202  typedef typename boost::detail::shared_state<R>::move_dest_type ReturnValue;
203 #else
204  typedef typename boost::detail::future_traits<R>::move_dest_type ReturnValue;
205 #endif
206 
211  operator ReturnValue() { return this->mFuture.get(); }
212 
225  ReturnValue get(bool throwXRPC = true, bool recursive = true)
226  {
227  if (throwXRPC)
228  return this->mFuture.get();
229 
230  try {
231  return this->mFuture.get();
232  }
233  catch (XRPC& ex) {
234  if (ex.hasOrigException())
235  ex.raiseOrigException(recursive);
236 
237  throw; // throw XRPC if it has no original exception stored
238  }
239  }
240 
241 };
242 
244 
250 template <>
251 class RPCFuture<void> : public RPCFutureCommon<void>
252 {
253 public:
255 
257  RPCFuture(boost::unique_future<void> other, AbstractRPCClient* client,
258  const std::string& callId) :
259  RPCFutureCommon<void>(client, callId)
260  {
261  this->mFuture.swap(other);
262  }
263 
265  RPCFuture(RPCFuture&& other) {
266  this->swap(other);
267  }
268 
271  this->swap(other);
272  return *this;
273  }
274 
289  void get(bool throwXRPC = true, bool recursive = true)
290  {
291  if (throwXRPC) {
292  this->mFuture.get();
293  } else {
294  try {
295  this->mFuture.get();
296  }
297  catch (XRPC& ex) {
298  if (ex.hasOrigException())
299  ex.raiseOrigException(recursive);
300 
301  throw; // throw XRPC if it has no original exception stored
302  }
303  }
304  }
305 
306 };
307 
309 
314 template <>
315 class RPCFuture<JSONRPCResponse> : public RPCFutureCommon<JSONRPCResponse>
316 {
317 public:
319 
321  RPCFuture(boost::unique_future<JSONRPCResponse> other, AbstractRPCClient* client,
322  const std::string& callId) :
323  RPCFutureCommon<JSONRPCResponse>(client, callId)
324  {
325  this->mFuture.swap(other);
326  }
327 
329  RPCFuture(RPCFuture&& other) {
330  this->swap(other);
331  }
332 
335  this->swap(other);
336  return *this;
337  }
338 
351  json::Value get(bool throwXRPC = true, bool recursive = true)
352  {
353  if (throwXRPC)
354  return this->mFuture.get().getResult();
355 
356  try {
357  return this->mFuture.get().getResult();
358  }
359  catch (XRPC& ex) {
360  if (ex.hasOrigException())
361  ex.raiseOrigException(recursive);
362 
363  throw; // throw XRPC if it has no original exception stored
364  }
365  }
366 
374  {
375  return this->mFuture.get().response;
376  }
377 
379  {
380  if (!this->mFuture.has_value())
381  return false;
382  try
383  {
384  get();
385  }
386  catch(...)
387  {
388  return true;
389  }
390  return false;
391  }
392 };
393 
395 
396 }
397 
398 #endif
bool hasException()
Definition: RPCFuture.h:378
RPCFuture(boost::unique_future< JSONRPCResponse > other, AbstractRPCClient *client, const std::string &callId)
internally used by RPCClient
Definition: RPCFuture.h:321
RPCFuture()
Definition: RPCFuture.h:176
RPCFuture & operator=(RPCFuture &&other)
move assignment operator
Definition: RPCFuture.h:334
Error codes for reasons of errors/exceptions while processing an rpc call.
RPCFuture(RPCFuture &&other)
move constructor
Definition: RPCFuture.h:187
RPCFuture & operator=(RPCFuture &&other)
move assignment operator
Definition: RPCFuture.h:192
RPCFutureCommon()
Definition: RPCFuture.h:72
bool timedWait(Duration const &relTime) const
Waits and blocks the current thread until the result of the associated RPC call is ready...
Definition: RPCFuture.h:122
RPCFutureCommon(AbstractRPCClient *client, const std::string &callId)
Definition: RPCFuture.h:74
An RPCFuture is a proxy for the result of an asynchronous RPC call.
Definition: RPCFuture.h:173
virtual void onDestructFuture(const std::string &callId)=0
Is called in the destructor of each RPCFuture to inform the client that we are no longer waiting for ...
bool hasOrigException()
Definition: RPCError.h:108
Wraps a JSON RPC call response.
Definition: JSONRPCResponse.h:61
Abstract interface for RPCClient.
RPCFuture(RPCFuture &&other)
move constructor
Definition: RPCFuture.h:265
Abstract interface for RPCClient.
Definition: AbstractRPCClient.h:60
An exception that is thrown by the RPCServer if an RPC call fails.
Definition: RPCError.h:76
bool hasValue() const
Returns true if the RPC call associated with this future has finished with a return value value rathe...
Definition: RPCFuture.h:104
~RPCFutureCommon()
Definition: RPCFuture.h:77
std::string mCallId
Definition: RPCFuture.h:147
Use this class to represent time durations.
Definition: Time.h:104
AbstractRPCClient * mClient
Definition: RPCFuture.h:146
Special response type for JSON RPC calls.
Wrapper for boost::unique_future that is specialized for RPC processing.
Definition: RPCFuture.h:68
RPCFuture & operator=(RPCFuture &&other)
move assignment operator
Definition: RPCFuture.h:270
json_spirit::mValue Value
A value is an abstract description of data in JSON (underlying data can either be one of the JSON bas...
Definition: JSON.h:176
bool hasException() const
Returns true if the RPC call associated with this future has finished with an exception rather than a...
Definition: RPCFuture.h:98
RPCFuture(boost::unique_future< R > other, AbstractRPCClient *client, const std::string &callId)
internally used by RPCClient
Definition: RPCFuture.h:179
RPCFuture()
Definition: RPCFuture.h:318
const std::string & callId()
query call ID
Definition: RPCFuture.h:87
RPCFuture()
Definition: RPCFuture.h:254
bool isReady() const
Checks to see if the result of the RPC call associated with this future is set.
Definition: RPCFuture.h:92
RPCFuture(RPCFuture &&other)
move constructor
Definition: RPCFuture.h:329
void raiseOrigException(bool recursive=false)
Definition: RPCError.h:109
void wait() const
Waits and blocks the current thread until the result of the associated RPC call is ready...
Definition: RPCFuture.h:111
RPCFuture(boost::unique_future< void > other, AbstractRPCClient *client, const std::string &callId)
internally used by RPCClient
Definition: RPCFuture.h:257
boost::unique_future< R > mFuture
Definition: RPCFuture.h:148
bool timedWaitUntil(boost::system_time const &absTime) const
Waits and blocks the current thread until the result of the associated RPC call is ready...
Definition: RPCFuture.h:133
boost::detail::future_traits< R >::move_dest_type ReturnValue
The rvalue return value, which essentially can be thought of R&amp;&amp;.
Definition: RPCFuture.h:204
void swap(RPCFutureCommon< R > &other)
Swaps ownership of the asynchronous results associated with other and *this.
Definition: RPCFuture.h:138
json::Value getAnswer()
Waits until the call has finished and returns the complete json rpc answer containing call id...
Definition: RPCFuture.h:373