homer512 icon

barrier

homer512 | PRO | 07/20/16 06:16:32 PM UTC | 0 ⭐ | 789 👁️ | Never ⏰ | []
C++ |

1.69 KB

|

None

|

0 👍

/

0 👎

#include <mutex>
// using std::mutex, std::unique_lock
#include <condition_variable>
// using std::condition_variable
#include <future>
// using std::async, std::future
#include <stdexcept>
// using std::invalid_argument
#include <array>
// using std::array
 
 
namespace {
 
  class barrier
  {
    std::mutex mutex;
    int sequence_no, count;
    const int total_count;
    std::condition_variable condition;
 
  public:
    explicit barrier(int total_count)
      : sequence_no(), count(), total_count(total_count)
    {
      if(total_count < 1)
        throw std::invalid_argument("barrier(total_count < 1)");
    }
    void wait()
    {
      std::unique_lock<std::mutex> lock(mutex);
      if(! count) {
        /* we are the first thread to arrive here. Let's set up the barrier */
        ++sequence_no;
        count = total_count;
      }
      if(--count) {
        const int own_seq_no = sequence_no;
        auto is_complete = [own_seq_no, this]() noexcept -> bool {
          return this->count == 0 || this->sequence_no != own_seq_no;
        };
        condition.wait(lock, is_complete);
      }
      else {
#      ifdef WAKE_AFTER
        lock.unlock();
#      endif
        condition.notify_all();
      }
    }
  };
 
 
  void threadfun(barrier* shared_barrier, int iterations)
  {
    for(int i = 0; i < iterations; ++i)
      shared_barrier->wait();
  }
}
 
int main()
{
  const int iterations = 1000;
  constexpr int threads = 16;
  std::array<std::future<void>, threads> futures;
  barrier shared_barrier(threads);
  for(std::future<void>& future: futures)
    future = std::async(std::launch::async, threadfun, &shared_barrier,
                        iterations);
  for(std::future<void>& future: futures)
    future.get();
}

Comments