casa  5.7.0-16
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Future.h
Go to the documentation of this file.
1 /* -*- mode: c++ -*- */
2 //# Future.h
3 //# Copyright (C) 2017
4 //# Associated Universities, Inc. Washington DC, USA.
5 //#
6 //# This library is free software; you can redistribute it and/or modify it
7 //# under the terms of the GNU Library General Public License as published by
8 //# the Free Software Foundation; either version 2 of the License, or (at your
9 //# option) any later version.
10 //#
11 //# This library is distributed in the hope that it will be useful, but WITHOUT
12 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
14 //# License for more details.
15 //#
16 //# You should have received a copy of the GNU Library General Public License
17 //# along with this library; if not, write to the Free Software Foundation,
18 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
19 //#
20 //# Correspondence concerning AIPS++ should be addressed as follows:
21 //# Internet email: aips2-request@nrao.edu.
22 //# Postal address: AIPS++ Project Office
23 //# National Radio Astronomy Observatory
24 //# 520 Edgemont Road
25 //# Charlottesville, VA 22903-2475 USA
26 //#
27 #ifndef FUTURE_H_
28 #define FUTURE_H_
29 
30 #include <future>
31 #include <msvis/MSVis/util/Try.h>
32 
33 namespace casa {
34 
35 namespace vi {
36 
37 // FutureBase exists to enable tests in Future template methods of whether
38 // Future::value_type is a Future type
39 struct FutureBase {};
40 
41 template <typename A>
42 class Future {
43 public:
44 
45  typedef A value_type;
46 
47  // Constructors
48 
49  Future() {
50  auto p = std::promise<Try<A> >();
51  p.set_value(Try<A>());
52  m_fta = p.get_future();
53  }
54 
55  Future(const A& a) {
56  auto p = std::promise<Try<A> >();
57  p.set_value(Try<A>(a));
58  m_fta = p.get_future();
59  }
60 
61  Future(A&& a) {
62  auto p = std::promise<Try<A> >();
63  p.set_value(Try<A>(std::move(a)));
64  m_fta = p.get_future();
65  }
66 
67  Future(const std::exception_ptr& e) {
68  auto p = std::promise<Try<A> >();
69  p.set_value(Try<A>(e));
70  m_fta = p.get_future();
71  }
72 
73  Future(std::exception_ptr&& e) {
74  auto p = std::promise<Try<A> >();
75  p.set_value(Try<A>(std::move(e)));
76  m_fta = p.get_future();
77  }
78 
79  Future(const std::shared_future<Try<A> >& f)
80  : m_fta(f) {}
81 
82  Future(std::shared_future<Try<A> >&& f)
83  : m_fta(std::move(f)) {}
84 
85  // NB: the following method would be erroneous, since calling
86  // std::future::share() is not const on std::future
87  //
88  // Future(const std::future<Try<A> >& f)
89  // : m_fta(f.share()) {};
90 
92  : m_fta(f.share()) {}
93 
94  // Static methods
95 
96  /* from()
97  *
98  * Type F should be callable () -> A
99  */
100  template <typename F,
101  class = std::enable_if<
102  std::is_convertible<std::result_of<F()>,A>::value,A> >
103  static Future<A>
104  from(F f) {
105  return Future<A>(
106  std::async(std::launch::async, [f](){ return try_(f); }));
107  }
108 
109  /* lift()
110  *
111  * Type F should be callable const A& -> B (for some B)
112  */
113  template <typename F,
114  typename B = typename std::result_of<F(const A&)>::type>
115 #if __cplusplus >= 201402L
116  static auto
117 #else
118  static std::function<Future<B>(const Future<A>&)>
119 #endif
120  lift(F f) {
121  return [f](const Future<A>& fa) {
122  return fa.map(f);
123  };
124  }
125 
126  // Instance methods
127 
128  /* flatMap()
129  *
130  * Type F should be callable const &A -> Future<B> (for some B)
131  */
132  template <typename F,
133  typename FB = typename std::result_of<F(const A&)>::type,
135  FB
136  flatMap(F&& fn) const {
137  return map(std::forward<F>(fn)).flatten();
138  }
139 
140  /* flatten()
141  *
142  * May only flatten instances of Future<Future<...> >, removes one level of
143  * Future
144  */
146  A
147  flatten() const {
148  auto fta = m_fta;
150  std::async(
151  std::launch::async,
152  [fta](){
153  return fta.get().recoverWith(
154  [](const std::exception_ptr& e) {
156  }).get().get();
157  }));
158  }
159 
160  /* followedBy()
161  *
162  * Type F should be callable () -> Future<B> (for some B)
163  */
164  template <typename F,
165  typename FB = typename std::result_of<F()>::type,
167  FB
168  followedBy(F fn) const {
169  return flatMap([fn](const A&){ return fn(); });
170  }
171 
172  /* forEffect()
173  *
174  * Type F should be callable () -> Future<anything>
175  */
176  template <typename F,
177  typename FB = typename std::result_of<F()>::type,
179  Future<A>
180  forEffect(F fn) const {
181  return flatMap(
182  [fn](const A& a){
183  return fn().map([a](const typename FB::value_type &){
184  return a;
185  });
186  });
187  }
188 
189  /* get()
190  */
191  Try<A>
192  get() const {
193  return m_fta.get();
194  }
195 
196  /* iterateUntil()
197  *
198  * Type P should be callable const A& -> bool
199  *
200  * Type F should be callable const A& -> Future<A>
201  */
202  template <typename P,
203  typename F,
204  class = std::enable_if<
205  std::is_convertible<std::result_of<P(const A&)>,bool>::value>,
206  class = std::enable_if<
207  std::is_same<Future<A>,std::result_of<F(const A&)> >::value> >
208  Future<A>
209  iterateUntil(P p, F&& f) const {
210  return iterateWhile(
211  [p](const A& a){ return !p(a); },
212  std::forward<F>(f));
213  }
214 
215  /* iterateWhile()
216  *
217  * Type P should be callable const A& -> bool
218  *
219  * Type F should be callable const A& -> Future<A>
220  */
221  template <typename P,
222  typename F,
223  class = std::enable_if<
224  std::is_convertible<std::result_of<P(const A&)>,bool>::value>,
225  class = std::enable_if<
226  std::is_same<Future<A>,std::result_of<F(const A&)> >::value> >
227  Future<A>
228  iterateWhile(P p, F f) const {
229  Future<A> fa = *this;
230  return
231  Future<A>(
232  std::async(
233  std::launch::async,
234  [fa, p, f]() {
235  auto result = fa;
236  while (result.get().map(p).getOrElse_(false))
237  result = result.flatMap(f);
238  return result.get();
239  }));
240  }
241 
242  /* map()
243  *
244  * Type F should be callable const A& -> B (for some B)
245  */
246  template <typename F,
247  typename B = typename std::result_of<F(const A&)>::type>
248  Future<B>
249  map(F fn) const {
250  auto fta = m_fta;
251  return Future<B>(
252  std::async(
253  std::launch::async,
254  [fta, fn](){ return fta.get().map(fn); }));
255  }
256 
257  /* recoverWith()
258  *
259  * Type F should be callable const std::exception_ptr & -> A
260  */
261  template <typename F,
262  class = std::enable_if<
263  std::is_convertible<
264  std::result_of<F(std::exception_ptr &)>,A>::value> >
265  Future<A>
266  recoverWith(F fn) const {
267  auto fta = m_fta;
268  return Future<A>(
269  std::async(
270  std::launch::async,
271  [fta, fn]() {
272  return fta.get().recoverWith(fn);
273  }));
274  }
275 
276  /* wait()
277  */
278  void
279  wait() const {
280  m_fta.wait();
281  }
282 
283  /* waitFor()
284  */
285  template <class Rep, class Period>
286  std::future_status
287  waitFor(const std::chrono::duration<Rep,Period>& rel_time) const {
288  return m_fta.wait_for(rel_time);
289  }
290 
291  /* waitUntil()
292  */
293  template <class Clock, class Duration>
294  std::future_status
295  waitUntil(const std::chrono::time_point<Clock,Duration>& abs_time) const {
296  return m_fta.wait_until(abs_time);
297  }
298 
299  /* operator>>=()
300  *
301  * Type F should be callable const A& -> Future<B> (for some B)
302  */
303  template <typename F,
304  typename FB = typename std::result_of<F(const A&)>::type,
306  FB
307  operator>>=(F&& fn) const {
308  return flatMap(std::forward<F>(fn));
309  }
310 
311  /* operator>>()
312  *
313  * Type F should be callable () -> Future<B> (for some B)
314  */
315  template <typename F,
316  typename FB = typename std::result_of<F()>::type,
318  FB
319  operator>>(F&& fn) const {
320  return followedBy(std::forward<F>(fn));
321  }
322 
323 
324  /* operator|()
325  *
326  * Type F should be callable const A& -> B (for some B)
327  */
328  template <typename F,
329  typename B = typename std::result_of<F(const A&)>::type>
330  Future<B>
331  operator|(F&& fn) const {
332  return map(std::forward<F>(fn));
333  }
334 
335 private:
336 
337  std::shared_future<Try<A> > m_fta;
338 
339 };
340 
341 template <typename F,
342  typename A = typename std::result_of<F()>::type>
343 Future<A>
344 future(F&& f) {
345  return Future<A>::from(std::forward<F>(f));
346 }
347 
348 
349 } // end namespace vi
350 
351 } // end namespace casa
352 
353 
354 #endif /* FUTURE_H_ */
void wait() const
Definition: Future.h:279
Future(const A &a)
Definition: Future.h:55
Future(const std::exception_ptr &e)
Definition: Future.h:67
FB followedBy(F fn) const
Definition: Future.h:168
std::shared_future< Try< A > > m_fta
Definition: Future.h:337
Try< A > try_(F &&f)
Definition: Try.h:415
Future< A > future(F &&f)
Definition: Future.h:344
Future()
Constructors.
Definition: Future.h:49
A flatten() const
Definition: Future.h:147
virtual void move(double dx, double dy, casacore::String system="")
Implements RegionShape::move.
Future< A > iterateUntil(P p, F &&f) const
Definition: Future.h:209
virtual casacore::String type() const
Implements RegionShape::type.
Definition: RegionShapes.h:548
Future< A > recoverWith(F fn) const
Definition: Future.h:266
Future(std::future< Try< A > > &&f)
NB: the following method would be erroneous, since calling std::future::share() is not const on std::...
Definition: Future.h:91
Future< B > map(F fn) const
Definition: Future.h:249
Future(const std::shared_future< Try< A > > &f)
Definition: Future.h:79
static Future< A > from(F f)
Static methods.
Definition: Future.h:104
FB operator>>=(F &&fn) const
Definition: Future.h:307
std::future_status waitUntil(const std::chrono::time_point< Clock, Duration > &abs_time) const
Definition: Future.h:295
FutureBase exists to enable tests in Future template methods of whether Future::value_type is a Futur...
Definition: Future.h:39
Future< B > operator|(F &&fn) const
Definition: Future.h:331
Future< A > iterateWhile(P p, F f) const
Definition: Future.h:228
Future(std::shared_future< Try< A > > &&f)
Definition: Future.h:82
FB flatMap(F &&fn) const
Instance methods.
Definition: Future.h:136
Future< A > forEffect(F fn) const
Definition: Future.h:180
static std::function< Future< B >const Future< A > &)> lift(F f)
Definition: Future.h:120
std::future_status waitFor(const std::chrono::duration< Rep, Period > &rel_time) const
Definition: Future.h:287
Future(std::exception_ptr &&e)
Definition: Future.h:73
const Double e
e and functions thereof:
FB operator>>(F &&fn) const
Definition: Future.h:319
LatticeExprNode value(const LatticeExprNode &expr)
This function returns the value of the expression without a mask.
Future(A &&a)
Definition: Future.h:61