piranha  0.10
thread_barrier.hpp
1 /* Copyright 2009-2017 Francesco Biscani (bluescarni@gmail.com)
2 
3 This file is part of the Piranha library.
4 
5 The Piranha library is free software; you can redistribute it and/or modify
6 it under the terms of either:
7 
8  * the GNU Lesser General Public License as published by the Free
9  Software Foundation; either version 3 of the License, or (at your
10  option) any later version.
11 
12 or
13 
14  * the GNU General Public License as published by the Free Software
15  Foundation; either version 3 of the License, or (at your option) any
16  later version.
17 
18 or both in parallel, as here.
19 
20 The Piranha library is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 for more details.
24 
25 You should have received copies of the GNU General Public License and the
26 GNU Lesser General Public License along with the Piranha library. If not,
27 see https://www.gnu.org/licenses/. */
28 
29 #ifndef PIRANHA_THREAD_BARRIER_HPP
30 #define PIRANHA_THREAD_BARRIER_HPP
31 
32 #include <condition_variable>
33 #include <cstdlib>
34 #include <mutex>
35 #include <stdexcept>
36 
37 #include <piranha/exceptions.hpp>
38 #include <piranha/thread_barrier.hpp>
39 
40 namespace piranha
41 {
42 
43 // This class has been minimally adapted from the barrier class in the Boost libraries 1.45.0.
44 // Original copyright notice follows:
45 
46 // Copyright (C) 2002-2003
47 // David Moore, William E. Kempf
48 // Copyright (C) 2007-8 Anthony Williams
49 //
50 // Distributed under the Boost Software License, Version 1.0. (See accompanying
51 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
52 
54 
65 {
66 public:
68 
76  explicit thread_barrier(unsigned count) : m_mutex(), m_cond(), m_threshold(count), m_count(count), m_generation(0)
77  {
78  if (count == 0) {
79  piranha_throw(std::invalid_argument, "count cannot be zero");
80  }
81  }
83  thread_barrier(const thread_barrier &) = delete;
85  thread_barrier(thread_barrier &&) = delete;
86 
87 private:
88  thread_barrier &operator=(const thread_barrier &) = delete;
89  thread_barrier &operator=(thread_barrier &&) = delete;
90 
91 public:
93 
97  {
98  try {
99  std::unique_lock<std::mutex> lock(m_mutex);
100  if (m_count != m_threshold) {
101  // NOTE: logging candidate.
102  std::abort();
103  }
104  } catch (...) {
105  // NOTE: logging candidate.
106  std::abort();
107  }
108  }
110 
116  bool wait()
117  {
118  try {
119  std::unique_lock<std::mutex> lock(m_mutex);
120  unsigned gen = m_generation;
121  if (--m_count == 0) {
122  // This is the last thread, update generation count
123  // and reset the count to the initial value, then
124  // notify the other threads.
125  ++m_generation;
126  m_count = m_threshold;
127  // NOTE: this is noexcept.
128  m_cond.notify_all();
129  return true;
130  }
131  // This is not the last thread, wait for the other threads
132  // to clear the barrier.
133  while (gen == m_generation) {
134  // NOTE: this will be noexcept in C++14.
135  m_cond.wait(lock);
136  }
137  return false;
138  } catch (...) {
139  // NOTE: logging candidate.
140  std::abort();
141  }
142  }
143 
144 private:
145  std::mutex m_mutex;
146  std::condition_variable m_cond;
147  const unsigned m_threshold;
148  unsigned m_count;
149  unsigned m_generation;
150 };
151 }
152 
153 #endif
thread_barrier(unsigned count)
Constructor.
~thread_barrier()
Destructor.
Exceptions.
#define piranha_throw(exception_type,...)
Exception-throwing macro.
Definition: exceptions.hpp:118
Root piranha namespace.
Definition: array_key.hpp:52
bool wait()
Wait method.