promise

Asynchronous tasks can store values in promises. The value (or the exception) stored in the promise is acquired by a future, which provides access to the stored value.

Promises are generally passed to threads, at which point the thread assigns a value to the promise. The calling thread, having created a future from the promise, can then access the assigned value.

#include <iostream>
#include <algorithm>
#include <vector>

#include <future>
#include <thread>

void find_largest
   (
   ::std::vector <int> const &
      values
         ,
   ::std::promise <int>
      maximum
   )
{
   maximum.set_value
      (
      *::std::max_element
         (
         values.begin()
            ,
         values.end()
         )
      )
      ;
}

int main(int argc, char ** argv)
{
   ::std::vector <int> const
      values = { 1, 2, 3, 4, 5 };
   
   ::std::promise <int>
      maximum;
   
   ::std::future <int>
      future = maximum.get_future();
   
   ::std::jthread
      worker
         (
         find_largest,
         ::std::ref(values),
         ::std::move(maximum)
         )
         ;
   
   ::std::cout << "Maximum Value: "
               << future.get()
               << ::std::endl
                  ;
   
   return 0;
}
Promises can also be used as signals. Use promise<void> and 'assign a value' using promise. set_value():
#include <iostream>
#include <algorithm>
#include <vector>

#include <future>
#include <thread>

void do_work
   (
   ::std::promise <void>
      signal
   )
{
   signal.set_value();
}

int main(int argc, char ** argv)
{
   ::std::promise <void>
      signal;
   
   auto
      future = signal.get_future();
   
   ::std::jthread
      worker
         (
         do_work,
         ::std::move(signal)
         )
         ;
   
   future.wait();
   
   return 0;
}