MIRA
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) noexcept {
188  this->swap(other);
189  }
190 
192  RPCFuture& operator=(RPCFuture && other) noexcept {
193  this->swap(other);
194  return *this;
195  }
196 
197 public:
198 
200 
201 #if BOOST_VERSION > 105600
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) noexcept {
266  this->swap(other);
267  }
268 
270  RPCFuture& operator=(RPCFuture && other) noexcept {
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) :
324  {
325  this->mFuture.swap(other);
326  }
327 
329  RPCFuture(RPCFuture&& other) noexcept {
330  this->swap(other);
331  }
332 
334  RPCFuture& operator=(RPCFuture && other) noexcept {
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
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
RPCFuture(RPCFuture &&other) noexcept
move constructor
Definition: RPCFuture.h:329
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) noexcept
move assignment operator
Definition: RPCFuture.h:334
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.
RPCFutureCommon()
Definition: RPCFuture.h:72
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
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
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 ...
void wait() const
Waits and blocks the current thread until the result of the associated RPC call is ready...
Definition: RPCFuture.h:111
bool hasOrigException()
Definition: RPCError.h:108
Wraps a JSON RPC call response.
Definition: JSONRPCResponse.h:61
Abstract interface for RPCClient.
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
~RPCFutureCommon()
Definition: RPCFuture.h:77
std::string mCallId
Definition: RPCFuture.h:147
Use this class to represent time durations.
Definition: Time.h:106
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) noexcept
move assignment operator
Definition: RPCFuture.h:192
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
RPCFuture(boost::unique_future< R > other, AbstractRPCClient *client, const std::string &callId)
internally used by RPCClient
Definition: RPCFuture.h:179
bool isReady() const
Checks to see if the result of the RPC call associated with this future is set.
Definition: RPCFuture.h:92
RPCFuture()
Definition: RPCFuture.h:318
RPCFuture(RPCFuture &&other) noexcept
move constructor
Definition: RPCFuture.h:265
const std::string & callId()
query call ID
Definition: RPCFuture.h:87
RPCFuture()
Definition: RPCFuture.h:254
void raiseOrigException(bool recursive=false)
Definition: RPCError.h:109
RPCFuture & operator=(RPCFuture &&other) noexcept
move assignment operator
Definition: RPCFuture.h:270
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
RPCFuture(RPCFuture &&other) noexcept
move constructor
Definition: RPCFuture.h:187
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
boost::detail::future_traits< R >::move_dest_type ReturnValue
The rvalue return value, which essentially can be thought of R&&.
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