GraphLab: Distributed Graph-Parallel API  2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
request_future.hpp
1 #ifndef OBJECT_REQUEST_FUTURE_HPP
2 #define OBJECT_REQUEST_FUTURE_HPP
3 #include <graphlab/serialization/serialization_includes.hpp>
4 #include <graphlab/rpc/dc_types.hpp>
5 #include <graphlab/rpc/dc_internal_types.hpp>
6 #include <graphlab/rpc/reply_increment_counter.hpp>
7 #include <graphlab/rpc/function_ret_type.hpp>
8 
9 namespace graphlab {
10 
11 
12  /**
13  * \ingroup rpc
14  * The result of a future_remote_request call.
15  * This class represents the outcome of a remote request sent to another
16  * machine via the future_remote_request_call. The future_remote_request call
17  * returns immediately with this object. Only when operator() is called on this
18  * object, then it waits for a result from the remote machine.
19  *
20  * example:
21  * \code
22  * // this function returns immediately
23  * graphlab::request_future<int> res =
24  * rmi.future_remote_request(SOME_OTHER_MACHINE,
25  * function_which_returns_an_integer, ...);
26  *
27  * ... we can do other stuff ...
28  * // read the result, or wait for the result if it is not done yet.
29  * int actual_result = res();
30  * \endcode
31  *
32  * The future object holds a copy of the result of the request, and the
33  * operator() call returns a reference to this result (once it is available).
34  */
35 template <typename T>
37  typedef typename dc_impl::function_ret_type<T>::type result_type;
38  mutable std::auto_ptr<dc_impl::reply_ret_type> reply;
39  result_type result;
40  bool hasval;
41 
42  /// default constructor
44  reply(new dc_impl::reply_ret_type(REQUEST_WAIT_METHOD)),
45  hasval(false) { }
46 
47  /** We can assign return values directly to the future in the
48  * case where no remote calls are necessary.
49  * Thus allowing the following to be written easily:
50  * \code
51  * request_future<int> a_function(int arg) {
52  * if (arg == 0) return rmi.future_remote_request(... somewhere else ...) ;
53  * else return 10;
54  * }
55  * \endcode
56  */
57  request_future(const T& val):
58  reply(NULL),
59  result(val),
60  hasval(true) { }
61 
62 
63  /// copy constructor
65  reply(val.reply),
66  result(val.result),
67  hasval(val.hasval) { }
68 
69  /// operator=
71  reply = val.reply;
72  result = val.result;
73  hasval = val.hasval;
74  return *this;
75  }
76 
77  /// explicit call to wait(). Will wait only if the future has no value yet
78  void wait() {
79  if (!hasval) {
80  reply->wait();
81  iarchive iarc(reply->val.c, reply->val.len);
82  iarc >> result;
83  reply->val.free();
84  hasval = true;
85  }
86  }
87 
88  bool is_ready() {
89  return (hasval || reply->flag == 0);
90  }
91 
92  /**
93  * Waits for the request if it has not yet been received.
94  * Otherwise, returns a reference to the received value.
95  */
96  result_type& operator()() {
97  if (!hasval) wait();
98  return result;
99  }
100 };
101 
102 
103 template <>
104 struct request_future<void> {
105  typedef dc_impl::function_ret_type<void>::type result_type;
106  mutable std::auto_ptr<dc_impl::reply_ret_type> reply;
107  bool hasval;
108 
109  request_future():
110  reply(new dc_impl::reply_ret_type(REQUEST_WAIT_METHOD)),
111  hasval(false) { }
112  request_future(int val):
113  reply(NULL),
114  hasval(true) { }
115 
116 
117  request_future(const request_future<void>& val):
118  reply(val.reply),
119  hasval(val.hasval) { }
120 
121  request_future& operator=(const request_future<void>& val) {
122  reply = val.reply;
123  hasval = val.hasval;
124  return *this;
125  }
126 
127  bool is_ready() {
128  return (hasval || reply->flag == 0);
129  }
130 
131 
132 
133  void wait() {
134  if (!hasval) {
135  result_type result;
136  reply->wait();
137  iarchive iarc(reply->val.c, reply->val.len);
138  iarc >> result;
139  reply->val.free();
140  hasval = true;
141  }
142  }
143 
144  result_type operator()() {
145  if (!hasval) wait();
146  return 0;
147  }
148 };
149 
150 
151 }
152 #endif