| // This file is part of Eigen, a lightweight C++ template library | 
 | // for linear algebra. | 
 | // | 
 | // Copyright (C) 2018 Rasmus Munk Larsen <rmlarsen@google.com> | 
 | // | 
 | // This Source Code Form is subject to the terms of the Mozilla | 
 | // Public License v. 2.0. If a copy of the MPL was not distributed | 
 | // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. | 
 |  | 
 | // Barrier is an object that allows one or more threads to wait until | 
 | // Notify has been called a specified number of times. | 
 |  | 
 | #ifndef EIGEN_CXX11_THREADPOOL_BARRIER_H | 
 | #define EIGEN_CXX11_THREADPOOL_BARRIER_H | 
 |  | 
 | #include "./InternalHeaderCheck.h" | 
 |  | 
 | namespace Eigen { | 
 |  | 
 | class Barrier { | 
 |  public: | 
 |   Barrier(unsigned int count) : state_(count << 1), notified_(false) { | 
 |     eigen_plain_assert(((count << 1) >> 1) == count); | 
 |   } | 
 |   ~Barrier() { eigen_plain_assert((state_ >> 1) == 0); } | 
 |  | 
 |   void Notify() { | 
 |     unsigned int v = state_.fetch_sub(2, std::memory_order_acq_rel) - 2; | 
 |     if (v != 1) { | 
 |       // Clear the lowest bit (waiter flag) and check that the original state | 
 |       // value was not zero. If it was zero, it means that notify was called | 
 |       // more times than the original count. | 
 |       eigen_plain_assert(((v + 2) & ~1) != 0); | 
 |       return;  // either count has not dropped to 0, or waiter is not waiting | 
 |     } | 
 |     std::unique_lock<std::mutex> l(mu_); | 
 |     eigen_plain_assert(!notified_); | 
 |     notified_ = true; | 
 |     cv_.notify_all(); | 
 |   } | 
 |  | 
 |   void Wait() { | 
 |     unsigned int v = state_.fetch_or(1, std::memory_order_acq_rel); | 
 |     if ((v >> 1) == 0) return; | 
 |     std::unique_lock<std::mutex> l(mu_); | 
 |     while (!notified_) { | 
 |       cv_.wait(l); | 
 |     } | 
 |   } | 
 |  | 
 |  private: | 
 |   std::mutex mu_; | 
 |   std::condition_variable cv_; | 
 |   std::atomic<unsigned int> state_;  // low bit is waiter flag | 
 |   bool notified_; | 
 | }; | 
 |  | 
 | // Notification is an object that allows a user to to wait for another | 
 | // thread to signal a notification that an event has occurred. | 
 | // | 
 | // Multiple threads can wait on the same Notification object, | 
 | // but only one caller must call Notify() on the object. | 
 | struct Notification : Barrier { | 
 |   Notification() : Barrier(1){}; | 
 | }; | 
 |  | 
 | }  // namespace Eigen | 
 |  | 
 | #endif  // EIGEN_CXX11_THREADPOOL_BARRIER_H |