title: pending std::future get of std::async with shared_from_this argument blocks destruction of this
body: <p>I wanted to create a class that would represent a task that can be started running asynchronously and will run continuously (effectively in a detached thread) until a stop signal is received. The usage for the sake of this question would look like this:</p>
  
  <pre><code>auto task = std::make_shared&lt;Task&gt;();
  task-&gt;start(); // starts the task running asynchronously
  ... after some time passes ...
  task-&gt;stop(); // signals to stop the task
  task-&gt;future.get(); // waits for task to stop running and return its result
  </code></pre>
  
  <p>However, a key feature of this <code>Task</code> class is that I cannot guarantee that the future will be waited/got... i.e. the last line may not get called before the shared pointer is destroyed.</p>
  
  <p>A stripped-down toy version of the class I wrote is as follows (please ignore that everything is in public, this is just for this example's simplicity):</p>
  
  <pre class="lang-cpp prettyprint-override"><code>class MyClass : public std::enable_shared_from_this&lt;MyClass&gt; {
  public:
      ~MyClass() { std::cout &lt;&lt; "Destructor called" &lt;&lt; std::endl; }
  
      void start() {
          future = std::async(std::launch::async, &amp;MyClass::method, this-&gt;shared_from_this());
      }
      void stop() { m_stop = true; }
  
      void method() {
          std::cout &lt;&lt; "running" &lt;&lt; std::endl;
          do {
              std::this_thread::sleep_for(std::chrono::seconds(1));
          } while(m_stop == false);
          std::cout &lt;&lt; "stopped" &lt;&lt; std::endl;
          return;
      }
      std::future&lt;void&gt; future;
      std::atomic&lt;bool&gt; m_stop = false;
  
  };
  </code></pre>
  
  <p>However, I discovered an undesirable feature of this code: if instead of <code>get</code> on the future, I just <code>wait</code> (e.g. if I don't care about the result of <code>method</code>, which in this case is a void anyway), then when <code>task</code> is deleted, the instance doesn't get destroyed.</p>
  
  <p>I.e. doing <code>task-&gt;future.get()</code> gives:</p>
  
  <pre><code>running
  stopped
  Destructor called
  </code></pre>
  
  <p>But <code>task-&gt;future.wait()</code> gives:</p>
  
  <pre><code>running
  stopped
  </code></pre>
  
  <p>From reading answer to <a href="https://stackoverflow.com/questions/49505280/what-is-the-lifetime-of-the-arguments-of-stdasync">What is the lifetime of the arguments of std::async?</a> I believe the problem here is the <code>this-&gt;shared_from_this()</code> argument to <code>std::async</code> won't be destroyed until the future from the async has been made invalid (through <code>get</code> or destruction or otherwise). So this shared_ptr is keeping the class instance alive.</p>
  
  <hr>
  
  <p><em>Solution Attempt 1:</em></p>
  
  <p>Replace the line in <code>start</code> with:</p>
  
  <pre class="lang-cpp prettyprint-override"><code>future  = std::async(std::launch::async, [this]() {
              return this-&gt;shared_from_this()-&gt;method();
          });
  </code></pre>
  
  <p>This ensures shared_ptr it creates is destroyed when the method completes, but I have been worried that there's nothing to stop <code>this</code> being destroyed between the time of it being captured by the lambda capture (which happens at this line, correct?) and the time the lambda is executed in the new thread. Is this a real possibility?</p>
  
  <hr>
  
  <p><em>Solution Attempt 2:</em></p>
  
  <p>To protect the <code>this</code> (<code>task</code>) being destroyed before the lambda function runs, I add another member variable <code>std::shared_ptr&lt;MyClass&gt; myself</code> then my start method can look like this:</p>
  
  <pre class="lang-cpp prettyprint-override"><code>myself = this-&gt;shared_from_this();
  future  = std::async(std::launch::async, [this]() {
              auto my_ptr = std::move(this-&gt;myself);
              return myself-&gt;method();
  });
  </code></pre>
  
  <p>Here the idea is that <code>myself</code> will ensure that if I delete the <code>task</code> shared_ptr, I don't destroy the class. Then inside the lambda, the shared_ptr is transferred to the local <code>my_ptr</code> variable, which is destroyed on exit.</p>
  
  <hr>
  
  <p>Are there issues with this solution, or have I overlooked a much cleaner way of achieving the sort functionality I'm after?</p>
  
  <p>Thanks!</p>