c++c++11lambdaatomicstdasync

std::atomic<bool> and lambda


Does anybody know why this program goes into an infinite loop, instead of stopping after 5s or so?

This happens with both the latest gcc and clang compiler; does atomic_bool suffer from hte same issues as a vector of bool?

If I use atomic<int> this works fine.

#include <algorithm>
#include <memory>
#include <utility>
#include <iostream>
#include <vector>
#include <functional>
#include <future>
#include <chrono>


using namespace std;
using namespace chrono_literals;

void send_heart_beat()
{
    cout << "sending heartbeat" << endl;
}

std::future<void> f;
int main()
{
   std::atomic<bool> stop(false);
   f = std::async(std::launch::async,[&stop]() { while(!stop) { send_heart_beat(); std::this_thread::sleep_for(1s); } });
   std::this_thread::sleep_for(5s);
   stop = true;
}

Solution

  •  std::atomic<bool> stop(false);
     std::future<void> f;
    

    These two variables are in different scopes, and f's scope is longer lived than stop's scope.

    f = std::async(std::launch::async,[&stop]() { while(!stop) { send_heart_beat(); std::this_thread::sleep_for(1s); } });
    

    here we bind a reference to stop into a lambda, and then store a (copy) of that lambda into an async object which is managed by f.

    When f goes out of scope, its destructor waits for the async task to finish. But because f's scope is longer lasting than stop's, we leave the scope of stop before f waits for the thread to finish.

    So our thread mindlessly continues accessing stop after stop no longer exists through a dangling reference.

    This results in undefined behavior; any behavior by your program is acceptable to the standard.