future

Futures are a way to access the results of asynchronous operations.

Threads can wait for the value of a future to be assigned. Futures provide a function named get which returns the value stored in the future after it is assigned.

Typically a future is created in one of 3 ways as follows:

Via the result of a packaged task:

#include <iostream>
#include <future>
#include <thread>

int main(int argc, char ** argv)
{
   //
   // Get a future from a packaged task:
   //
   
   ::std::packaged_task < int (void) >
      task( [] (void) { return 42; } );
   
   ::std::future <int>
      future = task.get_future();
   
   ::std::jthread
      thread( ::std::move( task ) );
   
   future.wait();
   
   ::std::cout << future.get() << ::std::endl;
   
   return 0;
}

Via a promise:

#include <iostream>
#include <future>
#include <thread>

int main(int argc, char ** argv)
{
   //
   // Get a future from a promise object:
   //
   
   ::std::promise <int>
      promise;
   
   ::std::future <int>
      future = promise.get_future();
   
   ::std::jthread
      thread( [&promise] { promise.set_value( 42 ); } );
   
   future.wait();
   
   ::std::cout << future.get() << ::std::endl;
   
   return 0;
}

Via ::std::async:

#include <iostream>
#include <future>
#include <thread>

int main(int argc, char ** argv)
{
   //
   // Get a future from ::std::async:
   //
   
   ::std::future <int>
      future =
         ::std::async
            (
            ::std::launch::async,
            [] (void) { return 42; }
            )
            ;
   
   future.wait();
   
   ::std::cout << future.get() << ::std::endl;
   
   return 0;
}

Futures can also be converted to ::std::shared_future objects, which can be copied. shared_futures can be used to make multiple threads wait for the same shared state.

shared_future<void> can be used to signal multiple threads:

#include <iostream>
#include <syncstream>

#include <future>
#include <thread>

void
do_work
   (
   unsigned
      thread_index
         ,
   ::std::shared_future <void>
      future
   )
{
   future.wait();
   
   ::std::osyncstream(::std::cout) << "Thread "
                                   << thread_index
                                   << " worked"
                                   << ::std::endl
                                      ;
   
   return;
}

int main(int argc, char ** argv)
{
   ::std::promise <void>
      is_ready;
   
   ::std::shared_future <void>
      future( is_ready.get_future() );
   
   ::std::jthread
      worker0( do_work, 0u, future ),
      worker1( do_work, 1u, future );
   
   is_ready.set_value();            // Activate both threads
   
   return 0;
}