SimGrid  3.16
Versatile Simulation of Distributed Systems
simgrid::kernel::Future< T > Class Template Reference

Detailed Description

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.

#include <future.hpp>

Public Member Functions

 Future ()=default
 
 Future (std::shared_ptr< FutureState< T >> state)
 
 Future (Future &)=delete
 
Futureoperator= (Future &)=delete
 
 Future (Future &&that)
 
Futureoperator= (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 thenNoUnwrap (F continuation) -> Future< decltype(continuation(std::move(*this)))>
 Attach a continuation to this future. More...
 
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...
 
get ()
 Get the value from the future. More...
 
 Future ()=default
 
 Future (std::shared_ptr< FutureState< T >> state)
 
 Future (Future &)=delete
 
Futureoperator= (Future &)=delete
 
 Future (Future &&that)
 
Futureoperator= (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 thenNoUnwrap (F continuation) -> Future< decltype(continuation(std::move(*this)))>
 Attach a continuation to this future. More...
 
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...
 
get ()
 Get the value from the future. More...
 

Constructor & Destructor Documentation

◆ Future() [1/8]

template<class T>
simgrid::kernel::Future< T >::Future ( )
default

◆ Future() [2/8]

template<class T>
simgrid::kernel::Future< T >::Future ( std::shared_ptr< FutureState< T >>  state)
inline

◆ Future() [3/8]

template<class T>
simgrid::kernel::Future< T >::Future ( Future< T > &  )
delete

◆ Future() [4/8]

template<class T>
simgrid::kernel::Future< T >::Future ( Future< T > &&  that)
inline

◆ Future() [5/8]

template<class T>
simgrid::kernel::Future< T >::Future ( )
default

◆ Future() [6/8]

template<class T>
simgrid::kernel::Future< T >::Future ( std::shared_ptr< FutureState< T >>  state)
inline

◆ Future() [7/8]

template<class T>
simgrid::kernel::Future< T >::Future ( Future< T > &  )
delete

◆ Future() [8/8]

template<class T>
simgrid::kernel::Future< T >::Future ( Future< T > &&  that)
inline

Member Function Documentation

◆ operator=() [1/4]

template<class T>
Future& simgrid::kernel::Future< T >::operator= ( Future< T > &  )
delete

◆ operator=() [2/4]

template<class T>
Future& simgrid::kernel::Future< T >::operator= ( Future< T > &&  that)
inline

◆ valid() [1/2]

template<class T>
bool simgrid::kernel::Future< T >::valid ( ) const
inline

Whether the future is valid:.

A future which as been used (.then of .get) becomes invalid.

We can use .then on a valid future.

◆ is_ready() [1/2]

template<class T>
bool simgrid::kernel::Future< T >::is_ready ( ) const
inline

Whether the future is ready.

A future is ready when it has an associated value or exception.

We can use .get() on ready futures.

◆ then_() [1/2]

template<class T>
template<class F >
void simgrid::kernel::Future< T >::then_ ( continuation)
inline

Attach a continuation to this future.

This is like .then() but avoid the creation of a new future.

◆ thenNoUnwrap() [1/2]

template<class T>
template<class F >
auto simgrid::kernel::Future< T >::thenNoUnwrap ( continuation) -> Future<decltype(continuation(std::move(*this)))>
inline

Attach a continuation to this future.

This version never does future unwrapping.

◆ then() [1/4]

template<class T>
template<class F >
auto simgrid::kernel::Future< T >::then ( continuation) -> typename std::enable_if<not is_future<decltype(continuation(std::move(*this)))>::value, Future<decltype(continuation(std::move(*this)))>>::type
inline

Attach a continuation to this future.

The future must be valid in order to make this call. The continuation is executed when the future becomes ready. The future becomes invalid after this call.

Parameters
continuationThis function is called with a ready future the future is ready
Exceptions
std::future_errorno state is associated with the future

◆ then() [2/4]

template<class T>
template<class F >
auto simgrid::kernel::Future< T >::then ( continuation) -> typename std::enable_if< is_future<decltype(continuation(std::move(*this)))>::value, decltype(continuation(std::move(*this))) >::type
inline

Attach a continuation to this future (future chaining)

◆ get() [1/2]

template<class T>
T simgrid::kernel::Future< T >::get ( )
inline

Get the value from the future.

The future must be valid and ready in order to make this call. std::future blocks when the future is not ready but we are completely single-threaded so blocking would be a deadlock. After the call, the future becomes invalid.

Returns
value of the future
Exceptions
anyException from the future
std::future_errorno state is associated with the future

◆ operator=() [3/4]

template<class T>
Future& simgrid::kernel::Future< T >::operator= ( Future< T > &  )
delete

◆ operator=() [4/4]

template<class T>
Future& simgrid::kernel::Future< T >::operator= ( Future< T > &&  that)
inline

◆ valid() [2/2]

template<class T>
bool simgrid::kernel::Future< T >::valid ( ) const
inline

Whether the future is valid:.

A future which as been used (.then of .get) becomes invalid.

We can use .then on a valid future.

◆ is_ready() [2/2]

template<class T>
bool simgrid::kernel::Future< T >::is_ready ( ) const
inline

Whether the future is ready.

A future is ready when it has an associated value or exception.

We can use .get() on ready futures.

◆ then_() [2/2]

template<class T>
template<class F >
void simgrid::kernel::Future< T >::then_ ( continuation)
inline

Attach a continuation to this future.

This is like .then() but avoid the creation of a new future.

◆ thenNoUnwrap() [2/2]

template<class T>
template<class F >
auto simgrid::kernel::Future< T >::thenNoUnwrap ( continuation) -> Future<decltype(continuation(std::move(*this)))>
inline

Attach a continuation to this future.

This version never does future unwrapping.

◆ then() [3/4]

template<class T>
template<class F >
auto simgrid::kernel::Future< T >::then ( continuation) -> typename std::enable_if<not is_future<decltype(continuation(std::move(*this)))>::value, Future<decltype(continuation(std::move(*this)))>>::type
inline

Attach a continuation to this future.

The future must be valid in order to make this call. The continuation is executed when the future becomes ready. The future becomes invalid after this call.

Parameters
continuationThis function is called with a ready future the future is ready
Exceptions
std::future_errorno state is associated with the future

◆ then() [4/4]

template<class T>
template<class F >
auto simgrid::kernel::Future< T >::then ( continuation) -> typename std::enable_if< is_future<decltype(continuation(std::move(*this)))>::value, decltype(continuation(std::move(*this))) >::type
inline

Attach a continuation to this future (future chaining)

◆ get() [2/2]

template<class T>
T simgrid::kernel::Future< T >::get ( )
inline

Get the value from the future.

The future must be valid and ready in order to make this call. std::future blocks when the future is not ready but we are completely single-threaded so blocking would be a deadlock. After the call, the future becomes invalid.

Returns
value of the future
Exceptions
anyException from the future
std::future_errorno state is associated with the future

The documentation for this class was generated from the following file: