Another SO thread explains how to use thread::native_handle
to do things that are outside the C++ threading API (e.g., set the priority of a thread). The gist is:
std::thread t(functionToRun);
auto nh = t.native_handle());
// configure t using nh
The problem with this approach is that functionToRun
may execute for an arbitrary amount of time (including to completion) before the code to configure t is finished.
I believe we can prevent that from happening as follows (untested):
std::atomic<bool> configured(false);
std::thread t([&]{ while (!configured); // spin until configured is true
functionToRun(); });
auto nh = t.native_handle();
// configure t using nh
configured = true;
Unfortunately, this causes the spawned thread to spin waiting for configured
to become true. It'd be preferable for the spawned thread to block until configuration is complete.
One way to accomplish that seems to be to use a mutex (also untested):
std::mutex m;
std::unique_lock<std::mutex> lock(m);
std::thread t([&]{ std::lock_guard<std::mutex> lg(m); // block until m available
functionToRun(); });
auto nh = t.native_handle();
// configure t using nh
lock.unlock(); // allow t to continue
This seems like it should work, but, conceptually, it seems like a condvar is more suited to the job of indicating when a condition (configuration is complete) is satisfied. But using a condvar requires all of the above, plus a condvar, and it would require dealing with the possibility of spurious wakes, which, as far as I know, is not an issue for mutexes.
Is there a better way to spawn a thread and then have it immediately stop so that I can use its native handle to configure it before allowing it to run further?