title: Is std::call_once reentrant and thread safe?
body: <p><a href="http://en.cppreference.com/w/cpp/thread/call_once" rel="nofollow">std::call_once</a>  is thread safe, but is it re-entrant as well?</p>
  
  <p>My testing using VS2012 (Debug &amp; Release) has shown that calling <code>std::call_once</code> recursively from a single thread is okay, but if the calls are made on separate threads it will cause a deadlock. Is this a known limitation of <code>std::call_once</code>?</p>
  
  <pre><code>#include "stdafx.h"
  
  #include &lt;iostream&gt;
  #include &lt;mutex&gt;
  #include &lt;thread&gt;
  
  void Foo()
  {
      std::cout &lt;&lt; "Foo start" &lt;&lt; std::endl;
  
      std::once_flag flag;
      std::call_once( flag, [](){
          std::cout &lt;&lt; "Hello World!" &lt;&lt; std::endl;
      });
  
      std::cout &lt;&lt; "Foo end" &lt;&lt; std::endl;
  }
  
  int _tmain(int argc, _TCHAR* argv[])
  {
      // Single threaded Works
      {
          std::once_flag fooFlag;
          std::call_once( fooFlag, Foo);      
      }
  
      // Works
      // Threaded version, join outside call_once
      {
          std::once_flag fooFlag;
          std::thread t;
          std::call_once( fooFlag, [&amp;t](){
              t = std::thread(Foo);
              std::this_thread::sleep_for(std::chrono::milliseconds(1000));
          }); 
          t.join();
      }
  
      // Dead locks
      // Threaded version, join inside call_once
      {
          std::once_flag fooFlag;
          std::call_once( fooFlag, [](){
              auto t = std::thread(Foo);
              t.join();
          });     
      }
  
      return 0;
  }
  </code></pre>
  
  <p>It seems like <code>std:call_once</code> is locking a static mutex that doesn't get unlocked until the function exits. In the single-threaded case it works because on the second call that thread already has the lock. On the threaded version it will block until the first call exits.</p>
  
  <p>I also noticed that if you change the <code>std::once_flag</code> flag in the <code>Foo()</code> function to <code>static</code> that the deadlock will still occur. </p>