template<class T>
class simgrid::kernel::Future< T >
Result of some (probably) asynchronous operation in the SimGrid kernel.
simgrid::simix::Future and simgrid::simix::Future provide an abstration for asynchronous stuff happening in the SimGrid kernel. They are based on C++1z futures.
The future represents a value which will be available at some point when this asynchronous operaiont is finished. Alternatively, if this operations fails, the result of the operation might be an exception.
As the operation is possibly no terminated yet, we cannot get the result yet. Moreover, as we cannot block in the SimGrid kernel we cannot wait for it. However, we can attach some code/callback/continuation which will be executed when the operation terminates.
Example of the API (simgrid::kernel::createProcess
does not exist):
// Create a new process using the Worker code, this process returns
// a std::string:
simgrid::kernel::Future<std::string> future =
simgrid::kernel::createProcess("worker42", host, Worker(42));
// At this point, we just created the process so the result is not available.
// However, we can attach some work do be done with this result:
future.then([](simgrid::kernel::Future<std::string> result) {
// This code is called when the operation is completed so the result is
// available:
try {
// Try to get value, this might throw an exception if the operation
// failed (such as an exception throwed by the worker process):
std::string value = result.get();
XBT_INFO("Value: %s", value.c_str());
}
catch(std::exception& e) {
// This is an exception from the asynchronous operation:
XBT_INFO("Error: %e", e.what());
}
);
This is based on C++1z std::future but with some differences:
- there is no thread synchronization (atomic, mutex, condition variable, etc.) because everything happens in the SimGrid event loop;
- it is purely asynchronous, you are expected to use
.then()
;
- inside the
.then()
, .get()
can be used;
.get()
can only be used when .is_ready()
(as everything happens in a single-thread, the future would be guaranted to deadlock if .get()
is called when the future is not ready);
- there is no future chaining support for now (
.then().then()
);
- there is no sharing (
shared_future
) for now.
|
| Future ()=default |
|
| Future (std::shared_ptr< FutureState< T >> state) |
|
| Future (Future &)=delete |
|
Future & | operator= (Future &)=delete |
|
| Future (Future &&that) |
|
Future & | operator= (Future &&that) |
|
bool | valid () const |
| Whether the future is valid:. More...
|
|
bool | is_ready () const |
| Whether the future is ready. More...
|
|
template<class F > |
void | then_ (F continuation) |
| Attach a continuation to this future. More...
|
|
template<class F > |
auto | then_no_unwrap (F continuation) -> Future< decltype(continuation(std::move(*this)))> |
| Attach a continuation to this future. More...
|
|
template<class F > |
auto | thenNoUnwrap (F continuation) -> Future< decltype(continuation(std::move(*this)))> |
|
template<class F > |
auto | then (F continuation) -> typename std::enable_if< not is_future< decltype(continuation(std::move(*this)))>::value, Future< decltype(continuation(std::move(*this)))>>::type |
| Attach a continuation to this future. More...
|
|
template<class F > |
auto | then (F continuation) -> typename std::enable_if< is_future< decltype(continuation(std::move(*this)))>::value, decltype(continuation(std::move(*this))) >::type |
| Attach a continuation to this future (future chaining) More...
|
|
T | get () |
| Get the value from the future. More...
|
|