10 #ifndef EIGEN_CXX11_THREADPOOL_RUNQUEUE_H
11 #define EIGEN_CXX11_THREADPOOL_RUNQUEUE_H
39 template <
typename Work,
unsigned kSize>
47 for (
unsigned i = 0;
i < kSize;
i++)
56 unsigned front =
front_.load(std::memory_order_relaxed);
58 uint8_t s =
e->state.load(std::memory_order_relaxed);
60 !
e->state.compare_exchange_strong(s,
kBusy, std::memory_order_acquire))
62 front_.store(front + 1 + (kSize << 1), std::memory_order_relaxed);
64 e->state.store(
kReady, std::memory_order_release);
71 unsigned front =
front_.load(std::memory_order_relaxed);
73 uint8_t s =
e->state.load(std::memory_order_relaxed);
75 !
e->state.compare_exchange_strong(s,
kBusy, std::memory_order_acquire))
77 Work
w = std::move(
e->w);
78 e->state.store(
kEmpty, std::memory_order_release);
80 front_.store(front, std::memory_order_relaxed);
88 unsigned back =
back_.load(std::memory_order_relaxed);
90 uint8_t s =
e->state.load(std::memory_order_relaxed);
92 !
e->state.compare_exchange_strong(s,
kBusy, std::memory_order_acquire))
95 back_.store(back, std::memory_order_relaxed);
97 e->state.store(
kReady, std::memory_order_release);
103 if (
Empty())
return Work();
105 unsigned back =
back_.load(std::memory_order_relaxed);
107 uint8_t s =
e->state.load(std::memory_order_relaxed);
109 !
e->state.compare_exchange_strong(s,
kBusy, std::memory_order_acquire))
111 Work
w = std::move(
e->w);
112 e->state.store(
kEmpty, std::memory_order_release);
113 back_.store(back + 1 + (kSize << 1), std::memory_order_relaxed);
120 if (
Empty())
return 0;
122 unsigned back =
back_.load(std::memory_order_relaxed);
125 if (
size > 1) mid = back + (
size - 1) / 2;
128 for (;
static_cast<int>(mid - back) >= 0; mid--) {
130 uint8_t s =
e->state.load(std::memory_order_relaxed);
132 if (s !=
kReady || !
e->state.compare_exchange_strong(
133 s,
kBusy, std::memory_order_acquire))
141 result->push_back(std::move(
e->w));
142 e->state.store(
kEmpty, std::memory_order_release);
146 back_.store(start + 1 + (kSize << 1), std::memory_order_relaxed);
152 unsigned Size()
const {
return SizeOrNotEmpty<true>(); }
156 bool Empty()
const {
return SizeOrNotEmpty<false>() == 0; }
166 static const unsigned kMask = kSize - 1;
167 static const unsigned kMask2 = (kSize << 1) - 1;
192 template<
bool NeedSizeEstimate>
196 unsigned front =
front_.load(std::memory_order_acquire);
199 unsigned back =
back_.load(std::memory_order_acquire);
200 unsigned front1 =
front_.load(std::memory_order_relaxed);
201 if (front != front1) {
203 std::atomic_thread_fence(std::memory_order_acquire);
206 if (NeedSizeEstimate) {
210 unsigned maybe_zero = ((front ^ back) &
kMask2);
228 if (
size >
static_cast<int>(kSize))
size = kSize;
229 return static_cast<unsigned>(
size);
#define eigen_plain_assert(condition)
Array< double, 1, 3 > e(1./3., 0.5, 2.)
#define EIGEN_ALWAYS_INLINE
void operator=(const RunQueue &)=delete
unsigned SizeOrNotEmpty() const
std::atomic< unsigned > front_
RunQueue(const RunQueue &)=delete
std::atomic< unsigned > back_
unsigned PopBackHalf(std::vector< Work > *result)
EIGEN_ALWAYS_INLINE unsigned CalculateSize(unsigned front, unsigned back) const
static const unsigned kMask2
static const unsigned kMask
std::atomic< uint8_t > state