2

別の SO スレッドthread::native_handleでは、C++ スレッド化 API の外部にある処理 (スレッドの優先順位の設定など)を使用する方法について説明しています。要点は次のとおりです。

std::thread t(functionToRun);
auto nh = t.native_handle());
// configure t using nh           

このアプローチの問題は、functionToRunt を構成するコードが完了する前に、任意の時間 (完了までを含む) 実行される可能性があることです。

次のようにして、それを防ぐことができると思います(テストされていません):

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;

残念ながら、これにより、生成されたスレッドconfiguredが true になるのを待ってスピンします。構成が完了するまで、生成されたスレッドをブロックすることが望ましいでしょう。

それを達成する1つの方法は、ミューテックスを使用することです(これもテストされていません):

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

これは機能するはずですが、概念的には、条件 (構成が完了) がいつ満たされるかを示す仕事には condvar の方が適しているようです。しかし、condvar を使用するには、上記のすべてに加えて condvar が必要であり、偽の wakes の可能性に対処する必要があります。これは、私の知る限り、ミューテックスの問題ではありません。

スレッドを生成してすぐに停止し、ネイティブ ハンドルを使用してそれを構成してから実行できるようにする、より良い方法はありますか?

4

1 に答える 1

7

外部構成が完了するまでスレッドのメイン関数の開始を遅らせたい場合は、future を使用します。これにより、スピン待機が回避され、ミューテックスまたは condvar と同じブロッキング プロパティがありますが、より明確な意図が提供されます。このパターンを使用すると、例を次のように記述できます。

std::promise<void> p;
std::thread t([&p]{
    p.get_future().wait();
    thread_func();
}

auto nh=t.native_handle();
// configure nh
p.set_value();

私は特に、このパターンをshared_futureマルチスレッド テストで使用するのが好きです --- こうすることで、テストが始まる前に、すべてのスレッドが実行され、準備が整っていることを確認できます。

于 2012-06-25T07:23:52.153 に答える