Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[xbt] Comment about xbt::Result
[simgrid.git] / include / xbt / future.hpp
index 316f68f..7211c4e 100644 (file)
 
 #include <utility>
 #include <exception>
+#include <stdexcept>
+
+#include <type_traits>
+
+
 
 namespace simgrid {
 namespace xbt {
 
-/** A value or an exception
+/** A value or an exception (or nothing)
  *
- *  The API is similar to the one of future and promise.
+ *  This is similar to optional<expected<T>> but it with a Future/Promise
+ *  like API.
+ *
+ *  Also the name it not so great.
  **/
 template<class T>
 class Result {
@@ -171,30 +179,40 @@ public:
   }
 };
 
-/** Fulfill a promise by executing a given code */
+/** Execute some code and set a promise or result accordingly
+ *
+ *  Roughly this does:
+ *
+ *  <pre>
+ *  promise.set_value(code());
+ *  </pre>
+ *
+ *  but it takes care of exceptions and works with void.
+ *
+ *  We might need this when working with generic code because
+ *  the trivial implementation does not work with `void` (before C++1z).
+ *
+ *  @param    code  What we want to do
+ *  @param  promise Where to want to store the result
+ */
 template<class R, class F>
 auto fulfillPromise(R& promise, F&& code)
 -> decltype(promise.set_value(code()))
 {
   try {
-    promise.set_value(code());
+    promise.set_value(std::forward<F>(code)());
   }
   catch(...) {
     promise.set_exception(std::current_exception());
   }
 }
 
-/** Fulfill a promise by executing a given code
- *
- *  This is a special version for `std::promise<void>` because the default
- *  version does not compile in this case.
- */
 template<class P, class F>
 auto fulfillPromise(P& promise, F&& code)
 -> decltype(promise.set_value())
 {
   try {
-    (code)();
+    std::forward<F>(code)();
     promise.set_value();
   }
   catch(...) {
@@ -202,6 +220,26 @@ auto fulfillPromise(P& promise, F&& code)
   }
 }
 
+/** Set a promise/result from a future/resul
+ *
+ *  Roughly this does:
+ *
+ *  <pre>promise.set_value(future);</pre>
+ *
+ *  but it takes care of exceptions and works with `void`.
+ *
+ *  We might need this when working with generic code because
+ *  the trivial implementation does not work with `void` (before C++1z).
+ *
+ *  @param promise output (a valid future or a result)
+ *  @param future  input (a ready/waitable future or a valid result)
+ */
+template<class P, class F> inline
+void setPromise(P& promise, F&& future)
+{
+  fulfillPromise(promise, [&]{ return std::forward<F>(future).get(); });
+}
+
 }
 }