rm_vision/tools/thread_safe_queue.hpp
2025-12-15 02:33:20 +08:00

111 lines
2.2 KiB
C++

#ifndef TOOLS__THREAD_SAFE_QUEUE_HPP
#define TOOLS__THREAD_SAFE_QUEUE_HPP
#include <condition_variable>
#include <functional>
#include <iostream>
#include <mutex>
#include <queue>
namespace tools
{
template <typename T, bool PopWhenFull = false>
class ThreadSafeQueue
{
public:
ThreadSafeQueue(
size_t max_size, std::function<void(void)> full_handler = [] {})
: max_size_(max_size), full_handler_(full_handler)
{
}
void push(const T & value)
{
std::unique_lock<std::mutex> lock(mutex_);
if (queue_.size() >= max_size_) {
if (PopWhenFull) {
queue_.pop();
} else {
full_handler_();
return;
}
}
queue_.push(value);
not_empty_condition_.notify_all();
}
void pop(T & value)
{
std::unique_lock<std::mutex> lock(mutex_);
not_empty_condition_.wait(lock, [this] { return !queue_.empty(); });
if (queue_.empty()) {
std::cerr << "Error: Attempt to pop from an empty queue." << std::endl;
return;
}
value = queue_.front();
queue_.pop();
}
T pop()
{
std::unique_lock<std::mutex> lock(mutex_);
not_empty_condition_.wait(lock, [this] { return !queue_.empty(); });
T value = std::move(queue_.front());
queue_.pop();
return std::move(value);
}
T front()
{
std::unique_lock<std::mutex> lock(mutex_);
not_empty_condition_.wait(lock, [this] { return !queue_.empty(); });
return queue_.front();
}
void back(T & value)
{
std::unique_lock<std::mutex> lock(mutex_);
if (queue_.empty()) {
std::cerr << "Error: Attempt to access the back of an empty queue." << std::endl;
return;
}
value = queue_.back();
}
bool empty()
{
std::unique_lock<std::mutex> lock(mutex_);
return queue_.empty();
}
void clear()
{
std::unique_lock<std::mutex> lock(mutex_);
while (!queue_.empty()) {
queue_.pop();
}
not_empty_condition_.notify_all(); // 如果其他线程正在等待队列不为空,这样可以唤醒它们
}
private:
std::queue<T> queue_;
size_t max_size_;
mutable std::mutex mutex_;
std::condition_variable not_empty_condition_;
std::function<void(void)> full_handler_;
};
} // namespace tools
#endif // TOOLS__THREAD_SAFE_QUEUE_HPP