c++ – Allow one thread to execute section while others wait and resume

I have a requirement that is summarized below.

void update()
{
  |   |   |   |
  |   |   |   |
  |   |   |   |
 |  |  |  |
  =============
      meat           <--- Only one thread must execute here, the rest should skip it.
  =============
  |   |   |   |  <--- Other threads wait here until the "first" thread is done w/ "meat"
  |   |   |   |
  |   |   |   |
  "https://codereview.stackexchange.com/"https://codereview.stackexchange.com/"https://codereview.stackexchange.com/"/
}

From an outsider perspective, “meat” should be executed just once (by the first thread that encounters it)

This post is similar but differs in that it also requires other threads to execute the meat code block one at a time.

// testExecutive.cpp
#include <atomic>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>

struct Target {
  int nhits = 0;
  inline void hit() { ++nhits; }
};

struct Executive {
  Executive() = delete;
  Executive(int _Id, Target &_Tgt) : m_Id(_Id), m_Ready(false), m_Tgt(_Tgt) {}
  void update() {
    { // only one thread can execute this
      std::scoped_lock<std::mutex> lk(m_Mtx);
      // std::cout << "++Acquired lk " << m_Id << " | tid: " <<
      // std::this_thread::get_id() << "++n";
      if (!m_Ready.load()) {
        // std::cout << "==Updating" << m_Id << " | tid: " <<
        // std::this_thread::get_id() << "==n";
        m_Ready.store(true);
        m_Tgt.hit();
        m_Cv.notify_all();
      }
      // std::cout << "++Releasing lk " << m_Id << " | tid: " <<
      // std::this_thread::get_id() << "++n";
    }

    // the rest should wait here
    std::mutex wait_mtx;
    std::unique_lock<std::mutex> lk(wait_mtx);
    m_Cv.wait(lk, (&)() -> bool { return m_Ready.load(); });
  }
  inline void reset() { m_Ready.store(false); }

private:
  int m_Id;
  Target &m_Tgt;
  std::condition_variable m_Cv;
  std::mutex m_Mtx;
  std::atomic_bool m_Ready;
};

int main(int argc, char *argv()) {
  int n(2);
  if (argc >= 2) {
    n = atoi(argv(1));
  }
  Target tgt;
  Executive e(1, tgt);
  auto updFn = (&e)() { e.update(); };

  // update same executive from 3 threads. Repeat n times.
  int i(n);
  while (i > 0) {
    e.reset();
    {
      std::thread t1(updFn), t2(updFn), t3(updFn);
      t1.join();
      t2.join();
      t3.join();
    }
    --i;
  }
  std::cout << (n == tgt.nhits ? "(OK)" : "(ERR)") << " Updates: " << n << " | "
            << "Hits: " << tgt.nhits << "n";
  return 0;
}

I setup a simple method to verify that exactly one out of three threads executes the desired code. The method hit() is called in Executive::Update. Compile and test like so.

jaswant@HAL9000:~$ g++ testExecutive.cpp -lpthread --std=c++17
jaswant@HAL9000:~$ ./a.out 2
(OK) Updates: 2 | Hits: 2
jaswant@HAL9000:~$ ./a.out 100
(OK) Updates: 100 | Hits: 100
jaswant@HAL9000:~$ ./a.out 2
(OK) Updates: 2 | Hits: 2
jaswant@HAL9000:~$ ./a.out 4
(OK) Updates: 4 | Hits: 4
jaswant@HAL9000:~$ ./a.out 8
(OK) Updates: 8 | Hits: 8
jaswant@HAL9000:~$ ./a.out 16
(OK) Updates: 16 | Hits: 16
jaswant@HAL9000:~$ ./a.out 256
(OK) Updates: 256 | Hits: 256
jaswant@HAL9000:~$ ./a.out 1024
(OK) Updates: 1024 | Hits: 1024
jaswant@HAL9000:~$ ./a.out 8192
(OK) Updates: 8192 | Hits: 8192
jaswant@HAL9000:~$ ./a.out 100000
(OK) Updates: 100000 | Hits: 100000

So, it works. Can anyone please point out bad usage of mutex/condition variables/locks and perhaps a way to do this w/o an atomic variable in the predicate?