Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Cosmetics: rename host::on to host::turnOn
[simgrid.git] / include / simgrid / simix.hpp
index 0cdf6ea..3b6b9a2 100644 (file)
@@ -24,24 +24,28 @@ XBT_PUBLIC(void) simcall_run_kernel(std::function<void()> const& code);
 namespace simgrid {
 namespace simix {
 
+/** Fulfill a promise by executing a given code */
 template<class R, class F>
 void fulfill_promise(std::promise<R>& promise, F&& code)
 {
   try {
-    promise.set_value(code());
+    promise.set_value(std::forward<F>(code)());
   }
   catch(...) {
     promise.set_exception(std::current_exception());
   }
 }
 
-// special version for R=void because the previous code does not compile
-// in this case:
+/** 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 F>
 void fulfill_promise(std::promise<void>& promise, F&& code)
 {
   try {
-    code();
+    std::forward<F>(code)();
     promise.set_value();
   }
   catch(...) {
@@ -49,13 +53,28 @@ void fulfill_promise(std::promise<void>& promise, F&& code)
   }
 }
 
+/** Execute some code in the kernel/maestro
+ *
+ *  This can be used to enforce mutual exclusion with other simcall.
+ *  More importantly, this enforces a deterministic/reproducible ordering
+ *  of the operation with respect to other simcalls.
+ */
 template<class F>
 typename std::result_of<F()>::type kernel(F&& code)
 {
+  // If we are in the maestro, we take the fast path and execute the
+  // code directly without simcall mashalling/unmarshalling/dispatch:
+  if (SIMIX_is_maestro())
+    return std::forward<F>(code)();
+
+  // If we are in the application, pass the code to the maestro which is
+  // executes it for us and reports the result. We use a std::future which
+  // conveniently handles the success/failure value for us.
   typedef typename std::result_of<F()>::type R;
   std::promise<R> promise;
   simcall_run_kernel([&]{
-    fulfill_promise(promise, code);
+    xbt_assert(SIMIX_is_maestro(), "Not in maestro");
+    fulfill_promise(promise, std::forward<F>(code));
   });
   return promise.get_future().get();
 }