call_once

call_once can be used to call a function (or a callable object) exactly once, even if it is executed by more than one thread.

It does this by accepting a flag as its first argument: the state of the flag indicates whether or not the callable object has been used.

#include <iostream>
#include <mutex>
#include <thread>

::std::once_flag
   once;

void worker(unsigned thread_id)
{
   ::std::call_once
      (
      once,
      [&thread_id]
      {
         ::std::cout << "Thread "
                     << thread_id
                     << " did the work"
                     << ::std::endl;
      }
      )
      ;
   
   return;
}

int main(int argc, char ** argv)
{
   ::std::jthread( worker, 0u );
   ::std::jthread( worker, 1u );
   ::std::jthread( worker, 2u );
   ::std::jthread( worker, 3u );
   
   return 0;
}
Possible output:
Thread 0 did the work

If the callable object raises an exception rather than returning normally, then the flag is not flipped and the next call to call_once will evaluate the callable again (and so on, until it does not raise an exception).

#include <iostream>
#include <exception>

#include <mutex>
#include <thread>

::std::once_flag
   once;

void worker(unsigned thread_id, bool do_raise_exception)
{
   try
   {
      ::std::call_once
         (
         once,
         [&]
         {
            //
            // Raise an exception if do_raise_exception
            // is true, otherwise return normally:
            //
            
            if (
                  do_raise_exception
               )
            {
               ::std::cout << "Thread "
                           << thread_id
                           << " raised an exception"
                           << ::std::endl;
               
               throw ::std::runtime_error("error");
               
               return;
            }
            
            ::std::cout << "Thread "
                        << thread_id
                        << " did the work"
                        << ::std::endl;
         }
         )
         ;
   }
   catch( ... )
   {
   }
   
   return;
}

int main(int argc, char ** argv)
{
   ::std::jthread( worker, 0u, true );
   ::std::jthread( worker, 1u, true );
   ::std::jthread( worker, 2u, false );
   ::std::jthread( worker, 3u, true );
   
   return 0;
}
Possible output:
Thread 0 raised an exception Thread 1 raised an exception Thread 2 did the work