From d1977b62d98f448de19f108f3a5bb49b1f2eee54 Mon Sep 17 00:00:00 2001 From: Gabriel Corona Date: Tue, 12 Jul 2016 16:47:37 +0200 Subject: [PATCH] [doc] Under the hood: simgrid::kernel::Future --- doc/doxygen/inside_extending.doc | 10 +++-- doc/doxygen/uhood.doc | 70 ++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/doc/doxygen/inside_extending.doc b/doc/doxygen/inside_extending.doc index 0ea39405ca..a0a8a97856 100644 --- a/doc/doxygen/inside_extending.doc +++ b/doc/doxygen/inside_extending.doc @@ -211,11 +211,12 @@ with the result: try { std::vector result = simgrid::simix::kernelSync([&] { // Fictional example, simgrid::kernel::readFile does not exist. - simgrid::Future> result = simgrid::kernel::readFile(file); + simgrid::kernel::Future> result = simgrid::kernel::readFile(file); return result; }); XBT_DEBUG("Finished reading file %s: length %zu", file, result.size()); } +// If the operation failed, kernelSync() throws an exception: catch (std::runtime_error& e) { XBT_ERROR("Could not read file %s", file); } @@ -228,7 +229,7 @@ like `kernelSync()` but does not block. Instead, it returns a ~~~ simgrid::simix::Future> result = simgrid::simix::kernelSync([&] { // Fictional example, simgrid::kernel::readFile does not exist. - simgrid::Future> result = simgrid::kernel::readFile(file); + simgrid::kernek::Future> result = simgrid::kernel::readFile(file); return result; }; @@ -239,9 +240,10 @@ while (!result.is_ready() && hasWorkToDo()) // We don't have anything to do, wait for the operation to complete and // get its value: try { - std:vector value = result.get(); - XBT_DEBUG("Finished reading file %s: length %zu", file, result.size()); + std:vector data = result.get(); + XBT_DEBUG("Finished reading file %s: length %zu", file, data.size()); } +// If the operation failed, .get() throws an exception: catch (std::runtime_error& e) { XBT_ERROR("Could not read file %s", file); } diff --git a/doc/doxygen/uhood.doc b/doc/doxygen/uhood.doc index 59963ed6ea..c022aec11d 100644 --- a/doc/doxygen/uhood.doc +++ b/doc/doxygen/uhood.doc @@ -1,9 +1,79 @@ /*! @page uhood Under the Hood +\tableofcontents + TBD - Simulation Loop, LMM, sharing -> papers - Context Switching, privatization -> papers - @subpage inside +\section simgrid_uhood_async Asynchronous operations + +\subsection simgrid_uhood_futures Futures + +The `simgrid::kernel::Future` class has been added to SimGrid as an abstraction +to represent asynchronous operations in the SimGrid maestro. Its API is based +on `std::experimental::future` from the [C++ Extensions for Concurrency Technical +Specification](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0159r0.html): + + - `simgrid::kernel::Future` represents the result an asynchronous operations + in the simulation inside the SimGrid maestro/kernel; + + - `simgrid::kernel::Promise` can be used to set the value of an assocaiated + `simgrid::kernel::Future`. + +The expected way to work with `simgrid::kernel::Future` is to add a +completion handler/continuation: + +~~~ +// This code is executed in the maestro context, we cannot block for the result +// to be ready: +simgrid::kernel::Future> result = simgrid::kernel::readFile(file); + +// Add a completion handler: +result.then([file](simgrid::kernel::Future> result) { + // At this point, the operation is complete and we can safely call .get(): + xbt_assert(result.is_ready()); + try { + std::vector data = result.get(); + XBT_DEBUG("Finished reading file %s: length %zu", file.c_str(), data.size()); + } + // If the operation failed, .get() throws an exception: + catch (std::runtime_error& e) { + XBT_ERROR("Could not read file %s", file.c_str()); + } +}); +~~~ + +The SimGrid kernel cannot block so calling `.get()` or `.wait()` on a +`simgrid::kernel::Future` which is not ready will deadlock. In practice, the +simulator detects this and aborts after reporting an error. + +In order to generate your own future, you might need to use a +`simgrid::kernel::Promise`. The promise is a one-way channel which can be +used to set the result of an associated `simgrid::kernel::Future` +(with either `.set_value()` or `.set_exception()`): + +~~~ +simgrid::kernel::Future kernel_wait_until(double date) +{ + auto promise = std::make_shared>(); + auto future = promise->get_future(); + SIMIX_timer_set(date, [promise] { + promise->set_value(); + }); + return future; +} +~~~ + +Like the experimental futures, we support chaining `.then()` methods with +automatic future unwrapping. +You might want to look at some [C++ tutorial on futures](https://www.youtube.com/watch?v=mPxIegd9J3w&list=PLHTh1InhhwT75gykhs7pqcR_uSiG601oh&index=43) +for more details and examples. Some operations of the proposed experimental +futures are currently not implemented in our futures however such as +`.wait_for()`, `.wait_until()`, `shared_future`, `when_any()`. + +\subsection simgrid_uhood_timer Timers + */ -- 2.20.1