Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread-safety of `std::function::operator()`

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;
}
like image 288
heiner Avatar asked Sep 15 '25 14:09

heiner


1 Answers

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.

like image 129
ALX23z Avatar answered Sep 18 '25 10:09

ALX23z