From: Gabriel Corona Date: Fri, 17 Jun 2016 11:01:25 +0000 (+0200) Subject: [simix] SIMIX futures X-Git-Tag: v3_14~967^2 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/6e16b58747eec5f035a6ffd4f5344d277dd1e753?hp=-c [simix] SIMIX futures --- 6e16b58747eec5f035a6ffd4f5344d277dd1e753 diff --git a/include/simgrid/simix/blocking_simcall.hpp b/include/simgrid/simix/blocking_simcall.hpp index aa85620fdb..59f688cab0 100644 --- a/include/simgrid/simix/blocking_simcall.hpp +++ b/include/simgrid/simix/blocking_simcall.hpp @@ -18,6 +18,7 @@ #include #include #include +#include XBT_PUBLIC(void) simcall_run_blocking(std::function const& code); @@ -68,6 +69,63 @@ auto blocking_simcall(F code) -> decltype(code().get()) return result.get(); } +/** A blocking (`wait()`-based) future for SIMIX processes */ +template +class Future { +public: + Future() {} + Future(simgrid::kernel::Future future) : future_(std::move(future)) {} + + bool valid() const { return future_.valid(); } + T get() + { + if (!valid()) + throw std::future_error(std::future_errc::no_state); + smx_process_t self = SIMIX_process_self(); + simgrid::xbt::Result result; + simcall_run_blocking([this, &result, self]{ + try { + // When the kernel future is ready... + this->future_.then([this, &result, self](simgrid::kernel::Future value) { + // ... wake up the process with the result of the kernel future. + simgrid::xbt::setPromise(result, value); + simgrid::simix::unblock(self); + }); + } + catch (...) { + result.set_exception(std::current_exception()); + simgrid::simix::unblock(self); + } + }); + return result.get(); + } + // TODO, wait() + // TODO, wait_for() + // TODO, wait_until() +private: + // We wrap an event-based kernel future: + simgrid::kernel::Future future_; +}; + +/** Start some asynchronous work + * + * @param code SimGrid kernel code which returns a simgrid::kernel::Future + * @return User future + */ +template +auto asynchronous_simcall(F code) + -> Future +{ + typedef decltype(code().get()) T; + + // Execute the code in the kernel and get the kernel simcall: + simgrid::kernel::Future future = + simgrid::simix::kernel(std::move(code)); + + // Wrap tyhe kernel simcall in a user simcall: + return simgrid::simix::Future(std::move(future)); +} + } } diff --git a/teshsuite/simix/generic_simcalls/generic_simcalls.cpp b/teshsuite/simix/generic_simcalls/generic_simcalls.cpp index f1743b585f..316065724d 100644 --- a/teshsuite/simix/generic_simcalls/generic_simcalls.cpp +++ b/teshsuite/simix/generic_simcalls/generic_simcalls.cpp @@ -75,6 +75,16 @@ static int master(int argc, char *argv[]) }); XBT_INFO("blocking_simcall with value returned with %i", res); + // Synchronize on a successul Future and get the value: + simgrid::simix::Future future = simgrid::simix::asynchronous_simcall([&] { + return kernel_defer(50, [] { + XBT_INFO("asynchronous_simcall with value"); + return 43; + }); + }); + res = future.get(); + XBT_INFO("asynchronous_simcall with value returned with %i", res); + return 0; } diff --git a/teshsuite/simix/generic_simcalls/generic_simcalls.tesh b/teshsuite/simix/generic_simcalls/generic_simcalls.tesh index 1c10ecb064..bd2dfd56e5 100644 --- a/teshsuite/simix/generic_simcalls/generic_simcalls.tesh +++ b/teshsuite/simix/generic_simcalls/generic_simcalls.tesh @@ -7,3 +7,5 @@ $ ${bindir:=.}/generic_simcalls --cfg=contexts/stack-size:96 ${srcdir:=.}/exampl > [Tremblay:master:(0) 20.000000] [test/INFO] Exception caught: Exception throwed from kernel_defer > [30.000000] [test/INFO] blocking_simcall with value > [Tremblay:master:(0) 30.000000] [test/INFO] blocking_simcall with value returned with 42 +> [50.000000] [test/INFO] asynchronous_simcall with value +> [Tremblay:master:(0) 50.000000] [test/INFO] asynchronous_simcall with value returned with 43