title: Non-obvious lifetime issue with std::promise and std::future
body: <p>This question is very similar to a previous one here: <a href="https://stackoverflow.com/questions/10843304/race-condition-in-pthread-once">race-condition in pthread_once()?</a></p>
  
  <p>It is essentially the same issue - the lifetime of a <code>std::promise</code> ending during a call to  <code>promise::set_value</code> (ie: after the associated future has been flagged, but before <code>pthread_once</code> has executed)</p>
  
  <p>So I know that my usage has this issue, and that I therefore cannot use it in this way. However, I think this is non-obvious. (In the wise words of Scott Meyer: <em>Make Interfaces Easy to Use Correctly and Hard to Use Incorrectly</em>)</p>
  
  <p>I present an exemplar below: </p>
  
  <ul>
  <li>I have a thread (<code>dispatcher</code>) which spins on a queue, popping a 'job' (a <code>std::function</code>) and executing it.</li>
  <li>I have a utility class called <code>synchronous_job</code> which blocks the calling thread until the 'job' has been executed on the dispatcher thread</li>
  <li>The <code>std::promise</code> and <code>std::future</code> are members of <code>synchronous_job</code> - once the <code>future</code> is set, the blocked calling thread continues, which results in the <code>synchronous_job</code> popping off the stack and being destructed.</li>
  <li>Unfortunately, at this time the <code>dispatcher</code> was context switched whilst <em>inside</em> <code>promise::set_value</code>; the <code>future</code> is flagged, but the call to <code>pthread_once</code> hasn't executed, and the pthread stack is somehow corrupted, meaning next time around: <strong>deadlock</strong> </li>
  </ul>
  
  <p>I would expect a call to <code>promise::set_value</code> to be atomic; the fact that it needs to do more work after it has flagged the <code>future</code> will inevitably lead to this kind of issue when using these classes in this manner.</p>
  
  <p>So my question is: How to achieve this kind of synchronisation using <code>std::promise</code> and <code>std::future</code>, keeping their lifetime associated with the class which provides this synchronisation mechanism?</p>
  
  <p>@Jonathan Wakely, could you perhaps use some RAII-style class internally which sets the <code>condition_variable</code> in its destructor after it flags the <code>future</code>? This would mean that even if the <code>promise</code> is destructed in the midst of a call to <code>set_value</code>, the additional work of setting the condition variable would complete correctly. Just an idea, not sure if you can use it...</p>
  
  <p>A full working example below, and the stack trace of the deadlocked app after:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;thread&gt;
  #include &lt;future&gt;
  #include &lt;queue&gt;
  
  struct dispatcher
  {
      dispatcher()
      {
          _thread = std::move(std::thread(&amp;dispatcher::loop, this));
      }
      void post(std::function&lt;void()&gt; job)
      {
          std::unique_lock&lt;std::mutex&gt; l(_mtx);
          _jobs.push(job);
          _cnd.notify_one();
      }
  private:
      void loop()
      {
          for (;;)
          {
              std::function&lt;void()&gt; job;
              {
                  std::unique_lock&lt;std::mutex&gt; l(_mtx);
                  while (_jobs.empty())
                      _cnd.wait(l);
                  job.swap(_jobs.front());
                  _jobs.pop();
              }
              job();
          }
      }
      std::thread                       _thread;
      std::mutex                        _mtx;
      std::condition_variable           _cnd;
      std::queue&lt;std::function&lt;void()&gt;&gt; _jobs;
  };
  //-------------------------------------------------------------
  
  struct synchronous_job
  {
      synchronous_job(std::function&lt;void()&gt; job, dispatcher&amp; d)
          : _job(job)
          , _d(d)
          , _f(_p.get_future())
      {
      }
      void run()
      {
          _d.post(std::bind(&amp;synchronous_job::cb, this));
          _f.wait();
      }
  private:
      void cb()
      {
          _job();
          _p.set_value();
      }
      std::function&lt;void()&gt; _job;
      dispatcher&amp;           _d;
      std::promise&lt;void&gt;    _p;
      std::future&lt;void&gt;     _f;
  };
  //-------------------------------------------------------------
  
  struct test
  {
      test()
          : _count(0)
      {
      }
      void run()
      {
          synchronous_job job(std::bind(&amp;test::cb, this), _d);
          job.run();
      }
  private:
      void cb()
      {
          std::cout &lt;&lt; ++_count &lt;&lt; std::endl;
      }
      int _count;
      dispatcher _d;
  };
  //-------------------------------------------------------------
  
  int main()
  {
      test t;
      for (;;)
      {
          t.run();
      }
  }
  </code></pre>
  
  <p>The stack trace of the deadlocked app:</p>
  
  <p><strong>Thread 1 (main thread)</strong></p>
  
  <pre><code>#0  0x00007fa112ed750c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
  #1  0x00007fa112a308ec in __gthread_cond_wait (__mutex=&lt;optimized out&gt;, __cond=&lt;optimized out&gt;) at /hostname/tmp/syddev/Build/gcc-4.6.2/gcc-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/x86_64-unknown-linux-gnu/bits/gthr-default.h:846
  #2  std::condition_variable::wait (this=&lt;optimized out&gt;, __lock=...) at ../../../../libstdc++-v3/src/condition_variable.cc:56
  #3  0x00000000004291d9 in std::condition_variable::wait&lt;std::__future_base::_State_base::wait()::{lambda()#1}&gt;(std::unique_lock&lt;std::mutex&gt;&amp;, std::__future_base::_State_base::wait()::{lambda()#1}) (this=0x78e050, __lock=..., __p=...) at /hostname/sdk/gcc470/suse11/x86_64/include/c++/4.7.0/condition_variable:93
  #4  0x00000000004281a8 in std::__future_base::_State_base::wait (this=0x78e018) at /hostname/sdk/gcc470/suse11/x86_64/include/c++/4.7.0/future:331
  #5  0x000000000042a2d6 in std::__basic_future&lt;void&gt;::wait (this=0x7fff0ae515c0) at /hostname/sdk/gcc470/suse11/x86_64/include/c++/4.7.0/future:576
  #6  0x0000000000428dd8 in synchronous_job::run (this=0x7fff0ae51580) at /home/lorimer/p4/Main/Source/Trading/Confucius/Test/Scratch/Test1/main.cpp:60
  #7  0x0000000000428f97 in test::run (this=0x7fff0ae51660) at /home/lorimer/p4/Main/Source/Trading/Confucius/Test/Scratch/Test1/main.cpp:83
  #8  0x0000000000427ad6 in main () at /home/lorimer/p4/Main/Source/Trading/Confucius/Test/Scratch/Test1/main.cpp:99
  </code></pre>
  
  <p><strong>Thread 2 (dispatcher thread)</strong></p>
  
  <pre><code>#0  0x00007fa112ed8b5b in pthread_once () from /lib64/libpthread.so.0
  #1  0x0000000000427946 in __gthread_once (__once=0x78e084, __func=0x4272d0 &lt;__once_proxy@plt&gt;) at /hostname/sdk/gcc470/suse11/x86_64/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/x86_64-unknown-linux-gnu/bits/gthr-default.h:718
  #2  0x000000000042948b in std::call_once&lt;void (std::__future_base::_State_base::*)(std::function&lt;std::unique_ptr&lt;std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter&gt; ()&gt;&amp;, bool&amp;), std::__future_base::_State_base* const, std::reference_wrapper&lt;std::function&lt;std::unique_ptr&lt;std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter&gt; ()&gt; &gt;, std::reference_wrapper&lt;bool&gt; &gt;(std::once_flag&amp;, void (std::__future_base::_State_base::*&amp;&amp;)(std::function&lt;std::unique_ptr&lt;std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter&gt; ()&gt;&amp;, bool&amp;), std::__future_base::_State_base* const&amp;&amp;, std::reference_wrapper&lt;std::function&lt;std::unique_ptr&lt;std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter&gt; ()&gt; &gt;&amp;&amp;, std::reference_wrapper&lt;bool&gt;&amp;&amp;) (__once=..., __f=
      @0x7fa111ff6be0: (void (std::__future_base::_State_base::*)(std::__future_base::_State_base * const, std::function&lt;std::unique_ptr&lt;std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter&gt;()&gt; &amp;, bool &amp;)) 0x42848a &lt;std::__future_base::_State_base::_M_do_set(std::function&lt;std::unique_ptr&lt;std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter&gt; ()&gt;&amp;, bool&amp;)&gt;) at /hostname/sdk/gcc470/suse11/x86_64/include/c++/4.7.0/mutex:819
  #3  0x000000000042827d in std::__future_base::_State_base::_M_set_result(std::function&lt;std::unique_ptr&lt;std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter&gt; ()&gt;, bool) (this=0x78e018, __res=..., __ignore_failure=false) at /hostname/sdk/gcc470/suse11/x86_64/include/c++/4.7.0/future:362
  #4  0x00000000004288d5 in std::promise&lt;void&gt;::set_value (this=0x7fff0ae515a8) at /hostname/sdk/gcc470/suse11/x86_64/include/c++/4.7.0/future:1206
  #5  0x0000000000428e2a in synchronous_job::cb (this=0x7fff0ae51580) at /home/lorimer/p4/Main/Source/Trading/Confucius/Test/Scratch/Test1/main.cpp:66
  #6  0x000000000042df53 in std::_Mem_fn&lt;void (synchronous_job::*)()&gt;::operator() (this=0x78c6e0, __object=0x7fff0ae51580) at /hostname/sdk/gcc470/suse11/x86_64/include/c++/4.7.0/functional:554
  #7  0x000000000042d77c in std::_Bind&lt;std::_Mem_fn&lt;void (synchronous_job::*)()&gt; (synchronous_job*)&gt;::__call&lt;void, , 0ul&gt;(std::tuple&lt;&gt;&amp;&amp;, std::_Index_tuple&lt;0ul&gt;) (this=0x78c6e0, __args=...) at /hostname/sdk/gcc470/suse11/x86_64/include/c++/4.7.0/functional:1156
  #8  0x000000000042cb28 in std::_Bind&lt;std::_Mem_fn&lt;void (synchronous_job::*)()&gt; (synchronous_job*)&gt;::operator()&lt;, void&gt;() (this=0x78c6e0) at /hostname/sdk/gcc470/suse11/x86_64/include/c++/4.7.0/functional:1215
  #9  0x000000000042b772 in std::_Function_handler&lt;void (), std::_Bind&lt;std::_Mem_fn&lt;void (synchronous_job::*)()&gt; (synchronous_job*)&gt; &gt;::_M_invoke(std::_Any_data const&amp;) (__functor=...) at /hostname/sdk/gcc470/suse11/x86_64/include/c++/4.7.0/functional:1926
  #10 0x0000000000429f2c in std::function&lt;void ()&gt;::operator()() const (this=0x7fa111ff6da0) at /hostname/sdk/gcc470/suse11/x86_64/include/c++/4.7.0/functional:2311
  #11 0x0000000000428c3c in dispatcher::loop (this=0x7fff0ae51668) at /home/lorimer/p4/Main/Source/Trading/Confucius/Test/Scratch/Test1/main.cpp:39
  </code></pre>