LoginSignup
17
16

More than 5 years have passed since last update.

C++11: ランデブー(バリア)によるスレッドの待ち合わせ

Posted at

N個のスレッドの待ち合わせ場所を用意する。
各スレッドがそこでwaitすると、
全員が揃うまで各スレッドは待ち状態となり、
全員が揃った時点で全スレッドの待ちが解ける。

こんな待ち合わせ場所(rendezvous)があれば、各スレッドをひとつずつjoinしなくていい。

#include <thread>
#include <mutex>
#include <condition_variable>
#include <stdexcept>

/* 
 * rendezvous(ランデブー) あるいは barrier(バリア)
 */
class rendezvous {
public:
    rendezvous(unsigned int count)
        : threshold_(count), count_(count), generation_(0) {
        if (count == 0) { throw std::invalid_argument("count cannot be zero."); }
    }

    bool wait() {
        std::unique_lock<std::mutex> lock(mutex_);
        unsigned int gen = generation_;
        if (--count_ == 0) {
            generation_++;
            count_ = threshold_;
            condition_.notify_all();
            return true;
        }
        condition_.wait(lock, [&](){return gen != generation_; });
        return false;
    }

private:
    std::mutex mutex_;
    std::condition_variable condition_;
    unsigned int threshold_;
    unsigned int count_;
    unsigned int generation_;
};

/* おためし */
#include <iostream>
#include <array>
#include <mutex>

using namespace std;

int main() {
    const int N = 4; // 子スレッド数
    array<thread,N> threads;

    rendezvous period(N);
    rendezvous quit(N+1);
    mutex mtx;

    for ( int i = 0; i < N; ++i ) {
        threads[i] = thread([&,i]() {
            { lock_guard<mutex> guard(mtx); cout << "thread " << i << " 位置について\n"; }
            period.wait(); // 全スレッドが揃うまで待機
            { lock_guard<mutex> guard(mtx); cout << "thread " << i << " よーい\n"; }
            period.wait(); // 全スレッドが揃うまで待機 
            { lock_guard<mutex> guard(mtx); cout << i << " どん!\n"; }
            quit.wait();
        });
    }
    quit.wait(); // 全スレッドが wait するまで待つ
    cout << "はい、次の組...\n";

    for (thread& thr : threads ) { thr.join(); }
}

/* 実行結果:
thread 0 位置について
thread 1 位置について
thread 2 位置について
thread 3 位置について
thread 3 よーい
thread 2 よーい
thread 0 よーい
thread 1 よーい
1 どん!
0 どん!
3 どん!
2 どん!
はい、次の組...
*/
17
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
16