Eigen::EventCount Class Reference

Classes

class  Waiter
 

Public Member Functions

void CancelWait ()
 
void CommitWait (Waiter *w)
 
 EventCount (MaxSizeVector< Waiter > &waiters)
 
void Notify (bool notifyAll)
 
void Prewait ()
 
 ~EventCount ()
 

Private Member Functions

 EventCount (const EventCount &)=delete
 
void operator= (const EventCount &)=delete
 
void Park (Waiter *w)
 
void Unpark (Waiter *w)
 

Static Private Member Functions

static void CheckState (uint64_t state, bool waiter=false)
 

Private Attributes

std::atomic< uint64_t > state_
 
MaxSizeVector< Waiter > & waiters_
 

Static Private Attributes

static const uint64_t kEpochBits
 
static const uint64_t kEpochInc
 
static const uint64_t kEpochMask
 
static const uint64_t kEpochShift
 
static const uint64_t kSignalInc
 
static const uint64_t kSignalMask
 
static const uint64_t kSignalShift
 
static const uint64_t kStackMask
 
static const uint64_t kWaiterBits
 
static const uint64_t kWaiterInc
 
static const uint64_t kWaiterMask
 
static const uint64_t kWaiterShift
 

Detailed Description

Definition at line 51 of file EventCount.h.

Constructor & Destructor Documentation

◆ EventCount() [1/2]

Eigen::EventCount::EventCount ( MaxSizeVector< Waiter > &  waiters)
inline

Definition at line 55 of file EventCount.h.

56  : state_(kStackMask), waiters_(waiters) {
57  eigen_plain_assert(waiters.size() < (1 << kWaiterBits) - 1);
58  }
#define eigen_plain_assert(condition)
Definition: Assert.h:156
MaxSizeVector< Waiter > & waiters_
Definition: EventCount.h:209
std::atomic< uint64_t > state_
Definition: EventCount.h:208
static const uint64_t kStackMask
Definition: EventCount.h:195
static const uint64_t kWaiterBits
Definition: EventCount.h:194

◆ ~EventCount()

Eigen::EventCount::~EventCount ( )
inline

Definition at line 60 of file EventCount.h.

60  {
61  // Ensure there are no waiters.
63  }

◆ EventCount() [2/2]

Eigen::EventCount::EventCount ( const EventCount )
privatedelete

Member Function Documentation

◆ CancelWait()

void Eigen::EventCount::CancelWait ( )
inline

Definition at line 111 of file EventCount.h.

111  {
112  uint64_t state = state_.load(std::memory_order_relaxed);
113  for (;;) {
114  CheckState(state, true);
115  uint64_t newstate = state - kWaiterInc;
116  // We don't know if the thread was also notified or not,
117  // so we should not consume a signal unconditionally.
118  // Only if number of waiters is equal to number of signals,
119  // we know that the thread was notified and we must take away the signal.
120  if (((state & kWaiterMask) >> kWaiterShift) ==
121  ((state & kSignalMask) >> kSignalShift))
122  newstate -= kSignalInc;
123  CheckState(newstate);
124  if (state_.compare_exchange_weak(state, newstate,
125  std::memory_order_acq_rel))
126  return;
127  }
128  }
static const uint64_t kSignalInc
Definition: EventCount.h:203
static const uint64_t kWaiterMask
Definition: EventCount.h:197
static const uint64_t kWaiterInc
Definition: EventCount.h:199
static const uint64_t kWaiterShift
Definition: EventCount.h:196
static void CheckState(uint64_t state, bool waiter=false)
Definition: EventCount.h:211
static const uint64_t kSignalMask
Definition: EventCount.h:201
static const uint64_t kSignalShift
Definition: EventCount.h:200
std::uint64_t uint64_t
Definition: Meta.h:41

◆ CheckState()

static void Eigen::EventCount::CheckState ( uint64_t  state,
bool  waiter = false 
)
inlinestaticprivate

Definition at line 211 of file EventCount.h.

211  {
212  static_assert(kEpochBits >= 20, "not enough bits to prevent ABA problem");
213  const uint64_t waiters = (state & kWaiterMask) >> kWaiterShift;
214  const uint64_t signals = (state & kSignalMask) >> kSignalShift;
215  eigen_plain_assert(waiters >= signals);
216  eigen_plain_assert(waiters < (1 << kWaiterBits) - 1);
217  eigen_plain_assert(!waiter || waiters > 0);
218  (void)waiters;
219  (void)signals;
220  }
static const uint64_t kEpochBits
Definition: EventCount.h:205

◆ CommitWait()

void Eigen::EventCount::CommitWait ( Waiter w)
inline

Definition at line 81 of file EventCount.h.

81  {
82  eigen_plain_assert((w->epoch & ~kEpochMask) == 0);
83  w->state = Waiter::kNotSignaled;
84  const uint64_t me = (w - &waiters_[0]) | w->epoch;
85  uint64_t state = state_.load(std::memory_order_seq_cst);
86  for (;;) {
87  CheckState(state, true);
88  uint64_t newstate;
89  if ((state & kSignalMask) != 0) {
90  // Consume the signal and return immediately.
91  newstate = state - kWaiterInc - kSignalInc;
92  } else {
93  // Remove this thread from pre-wait counter and add to the waiter stack.
94  newstate = ((state & kWaiterMask) - kWaiterInc) | me;
95  w->next.store(state & (kStackMask | kEpochMask),
96  std::memory_order_relaxed);
97  }
98  CheckState(newstate);
99  if (state_.compare_exchange_weak(state, newstate,
100  std::memory_order_acq_rel)) {
101  if ((state & kSignalMask) == 0) {
102  w->epoch += kEpochInc;
103  Park(w);
104  }
105  return;
106  }
107  }
108  }
RowVector3d w
static const uint64_t kEpochMask
Definition: EventCount.h:206
static const uint64_t kEpochInc
Definition: EventCount.h:207
void Park(Waiter *w)
Definition: EventCount.h:222

◆ Notify()

void Eigen::EventCount::Notify ( bool  notifyAll)
inline

Definition at line 132 of file EventCount.h.

132  {
133  std::atomic_thread_fence(std::memory_order_seq_cst);
134  uint64_t state = state_.load(std::memory_order_acquire);
135  for (;;) {
136  CheckState(state);
137  const uint64_t waiters = (state & kWaiterMask) >> kWaiterShift;
138  const uint64_t signals = (state & kSignalMask) >> kSignalShift;
139  // Easy case: no waiters.
140  if ((state & kStackMask) == kStackMask && waiters == signals) return;
141  uint64_t newstate;
142  if (notifyAll) {
143  // Empty wait stack and set signal to number of pre-wait threads.
144  newstate =
145  (state & kWaiterMask) | (waiters << kSignalShift) | kStackMask;
146  } else if (signals < waiters) {
147  // There is a thread in pre-wait state, unblock it.
148  newstate = state + kSignalInc;
149  } else {
150  // Pop a waiter from list and unpark it.
151  Waiter* w = &waiters_[state & kStackMask];
152  uint64_t next = w->next.load(std::memory_order_relaxed);
153  newstate = (state & (kWaiterMask | kSignalMask)) | next;
154  }
155  CheckState(newstate);
156  if (state_.compare_exchange_weak(state, newstate,
157  std::memory_order_acq_rel)) {
158  if (!notifyAll && (signals < waiters))
159  return; // unblocked pre-wait thread
160  if ((state & kStackMask) == kStackMask) return;
161  Waiter* w = &waiters_[state & kStackMask];
162  if (!notifyAll) w->next.store(kStackMask, std::memory_order_relaxed);
163  Unpark(w);
164  return;
165  }
166  }
167  }
void Unpark(Waiter *w)
Definition: EventCount.h:230

◆ operator=()

void Eigen::EventCount::operator= ( const EventCount )
privatedelete

◆ Park()

void Eigen::EventCount::Park ( Waiter w)
inlineprivate

Definition at line 222 of file EventCount.h.

222  {
223  EIGEN_MUTEX_LOCK lock(w->mu);
224  while (w->state != Waiter::kSignaled) {
225  w->state = Waiter::kWaiting;
226  w->cv.wait(lock);
227  }
228  }
#define EIGEN_MUTEX_LOCK
Definition: ThreadPool:58

◆ Prewait()

void Eigen::EventCount::Prewait ( )
inline

Definition at line 68 of file EventCount.h.

68  {
69  uint64_t state = state_.load(std::memory_order_relaxed);
70  for (;;) {
71  CheckState(state);
72  uint64_t newstate = state + kWaiterInc;
73  CheckState(newstate);
74  if (state_.compare_exchange_weak(state, newstate,
75  std::memory_order_seq_cst))
76  return;
77  }
78  }

◆ Unpark()

void Eigen::EventCount::Unpark ( Waiter w)
inlineprivate

Definition at line 230 of file EventCount.h.

230  {
231  for (Waiter* next; w; w = next) {
232  uint64_t wnext = w->next.load(std::memory_order_relaxed) & kStackMask;
233  next = wnext == kStackMask ? nullptr : &waiters_[internal::convert_index<size_t>(wnext)];
234  unsigned state;
235  {
236  EIGEN_MUTEX_LOCK lock(w->mu);
237  state = w->state;
238  w->state = Waiter::kSignaled;
239  }
240  // Avoid notifying if it wasn't waiting.
241  if (state == Waiter::kWaiting) w->cv.notify_one();
242  }
243  }

Member Data Documentation

◆ kEpochBits

const uint64_t Eigen::EventCount::kEpochBits
staticprivate

Definition at line 205 of file EventCount.h.

◆ kEpochInc

const uint64_t Eigen::EventCount::kEpochInc
staticprivate

Definition at line 207 of file EventCount.h.

◆ kEpochMask

const uint64_t Eigen::EventCount::kEpochMask
staticprivate

Definition at line 206 of file EventCount.h.

◆ kEpochShift

const uint64_t Eigen::EventCount::kEpochShift
staticprivate

Definition at line 204 of file EventCount.h.

◆ kSignalInc

const uint64_t Eigen::EventCount::kSignalInc
staticprivate

Definition at line 203 of file EventCount.h.

◆ kSignalMask

const uint64_t Eigen::EventCount::kSignalMask
staticprivate

Definition at line 201 of file EventCount.h.

◆ kSignalShift

const uint64_t Eigen::EventCount::kSignalShift
staticprivate

Definition at line 200 of file EventCount.h.

◆ kStackMask

const uint64_t Eigen::EventCount::kStackMask
staticprivate

Definition at line 195 of file EventCount.h.

◆ kWaiterBits

const uint64_t Eigen::EventCount::kWaiterBits
staticprivate

Definition at line 194 of file EventCount.h.

◆ kWaiterInc

const uint64_t Eigen::EventCount::kWaiterInc
staticprivate

Definition at line 199 of file EventCount.h.

◆ kWaiterMask

const uint64_t Eigen::EventCount::kWaiterMask
staticprivate

Definition at line 197 of file EventCount.h.

◆ kWaiterShift

const uint64_t Eigen::EventCount::kWaiterShift
staticprivate

Definition at line 196 of file EventCount.h.

◆ state_

std::atomic<uint64_t> Eigen::EventCount::state_
private

Definition at line 208 of file EventCount.h.

◆ waiters_

MaxSizeVector<Waiter>& Eigen::EventCount::waiters_
private

Definition at line 209 of file EventCount.h.


The documentation for this class was generated from the following file: