Is it safe to call a std::function<void(int)>& from several threads, provided the underlying lambda is thread-safe?
For instance (Godbolt link):
void target(int i, std::deque<std::function<void(int)>>* queue) {
  std::function<void(int)>& f = queue->front();
  f(i);
}
int main() {
  std::mutex mu;
  int count = 0;
  std::function<void(int)> f = [&](int i) {
    std::unique_lock<std::mutex> lock(mu);
    count += i;
  };
  std::deque<std::function<void(int)>> queue;
  queue.push_back(std::move(f));
  std::vector<std::thread> threads;
  for (int i = 0; i < 32; ++i) {
    threads.emplace_back(target, i, &queue);
  }
  for (std::thread& thread : threads) {
     thread.join();
  }
  std::cout << count << std::endl;
}
The operator () of std::function is marked as const. See https://en.cppreference.com/w/cpp/utility/functional/function/operator() therefore calling it from multiple threads is thread-safe as it causes no changes to the std::function. The lambda function that the std::function wraps modifies an external variable guarded by a mutex so it is thread-safe too.
Thus the operations are thread-safe.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With