|
|
|
@ -45,12 +45,12 @@ public:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PopWait(T& t, std::stop_token stop_token) {
|
|
|
|
|
Wait(stop_token);
|
|
|
|
|
ConsumerWait(stop_token);
|
|
|
|
|
Pop(t);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
T PopWait(std::stop_token stop_token) {
|
|
|
|
|
Wait(stop_token);
|
|
|
|
|
ConsumerWait(stop_token);
|
|
|
|
|
T t;
|
|
|
|
|
Pop(t);
|
|
|
|
|
return t;
|
|
|
|
@ -88,9 +88,10 @@ private:
|
|
|
|
|
}
|
|
|
|
|
} else if constexpr (Mode == PushMode::Wait) {
|
|
|
|
|
// Wait until we have free slots to write to.
|
|
|
|
|
while ((write_index - m_read_index.load()) == Capacity) {
|
|
|
|
|
std::this_thread::yield();
|
|
|
|
|
}
|
|
|
|
|
std::unique_lock lock{producer_cv_mutex};
|
|
|
|
|
producer_cv.wait(lock, [this, write_index] {
|
|
|
|
|
return (write_index - m_read_index.load()) < Capacity;
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
static_assert(Mode < PushMode::Count, "Invalid PushMode.");
|
|
|
|
|
}
|
|
|
|
@ -105,8 +106,8 @@ private:
|
|
|
|
|
++m_write_index;
|
|
|
|
|
|
|
|
|
|
// Notify the consumer that we have pushed into the queue.
|
|
|
|
|
std::scoped_lock lock{cv_mutex};
|
|
|
|
|
cv.notify_one();
|
|
|
|
|
std::scoped_lock lock{consumer_cv_mutex};
|
|
|
|
|
consumer_cv.notify_one();
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@ -122,9 +123,10 @@ private:
|
|
|
|
|
}
|
|
|
|
|
} else if constexpr (Mode == PushMode::Wait) {
|
|
|
|
|
// Wait until we have free slots to write to.
|
|
|
|
|
while ((write_index - m_read_index.load()) == Capacity) {
|
|
|
|
|
std::this_thread::yield();
|
|
|
|
|
}
|
|
|
|
|
std::unique_lock lock{producer_cv_mutex};
|
|
|
|
|
producer_cv.wait(lock, [this, write_index] {
|
|
|
|
|
return (write_index - m_read_index.load()) < Capacity;
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
static_assert(Mode < PushMode::Count, "Invalid PushMode.");
|
|
|
|
|
}
|
|
|
|
@ -139,8 +141,8 @@ private:
|
|
|
|
|
++m_write_index;
|
|
|
|
|
|
|
|
|
|
// Notify the consumer that we have pushed into the queue.
|
|
|
|
|
std::scoped_lock lock{cv_mutex};
|
|
|
|
|
cv.notify_one();
|
|
|
|
|
std::scoped_lock lock{consumer_cv_mutex};
|
|
|
|
|
consumer_cv.notify_one();
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@ -161,6 +163,10 @@ private:
|
|
|
|
|
|
|
|
|
|
// Increment the read index.
|
|
|
|
|
++m_read_index;
|
|
|
|
|
|
|
|
|
|
// Notify the producer that we have popped off the queue.
|
|
|
|
|
std::unique_lock lock{producer_cv_mutex};
|
|
|
|
|
producer_cv.notify_one();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Pop(T& t) {
|
|
|
|
@ -180,12 +186,16 @@ private:
|
|
|
|
|
// Increment the read index.
|
|
|
|
|
++m_read_index;
|
|
|
|
|
|
|
|
|
|
// Notify the producer that we have popped off the queue.
|
|
|
|
|
std::scoped_lock lock{producer_cv_mutex};
|
|
|
|
|
producer_cv.notify_one();
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Wait(std::stop_token stop_token) {
|
|
|
|
|
std::unique_lock lock{cv_mutex};
|
|
|
|
|
Common::CondvarWait(cv, lock, stop_token, [this] { return !Empty(); });
|
|
|
|
|
void ConsumerWait(std::stop_token stop_token) {
|
|
|
|
|
std::unique_lock lock{consumer_cv_mutex};
|
|
|
|
|
Common::CondvarWait(consumer_cv, lock, stop_token, [this] { return !Empty(); });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
alignas(128) std::atomic_size_t m_read_index{0};
|
|
|
|
@ -193,8 +203,10 @@ private:
|
|
|
|
|
|
|
|
|
|
std::array<T, Capacity> m_data;
|
|
|
|
|
|
|
|
|
|
std::condition_variable_any cv;
|
|
|
|
|
std::mutex cv_mutex;
|
|
|
|
|
std::condition_variable_any producer_cv;
|
|
|
|
|
std::mutex producer_cv_mutex;
|
|
|
|
|
std::condition_variable_any consumer_cv;
|
|
|
|
|
std::mutex consumer_cv_mutex;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <typename T, size_t Capacity = detail::DefaultCapacity>
|
|
|
|
|