2022-11-30 07:24:09 +08:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <condition_variable>
|
|
|
|
#include <mutex>
|
|
|
|
#include <queue>
|
|
|
|
#include <utility>
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
class BoundedQueue
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
explicit
|
|
|
|
BoundedQueue(std::size_t max_size_,
|
|
|
|
bool block_ = true)
|
2023-04-24 11:33:48 +08:00
|
|
|
: _block(block_),
|
|
|
|
_max_size(max_size_ ? max_size_ : 1)
|
2022-11-30 07:24:09 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-04-24 11:33:48 +08:00
|
|
|
BoundedQueue(const BoundedQueue&) = delete;
|
|
|
|
BoundedQueue(BoundedQueue&&) = default;
|
|
|
|
|
2022-11-30 07:24:09 +08:00
|
|
|
bool
|
|
|
|
push(const T& item_)
|
|
|
|
{
|
|
|
|
{
|
2023-04-24 11:33:48 +08:00
|
|
|
std::unique_lock<std::mutex> guard(_queue_lock);
|
2022-11-30 07:24:09 +08:00
|
|
|
|
|
|
|
_condition_push.wait(guard, [&]() { return _queue.size() < _max_size || !_block; });
|
|
|
|
|
|
|
|
if(_queue.size() == _max_size)
|
|
|
|
return false;
|
|
|
|
|
2023-04-24 11:33:48 +08:00
|
|
|
_queue.push(item_);
|
2022-11-30 07:24:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
_condition_pop.notify_one();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
push(T&& item_)
|
|
|
|
{
|
|
|
|
{
|
2023-04-24 11:33:48 +08:00
|
|
|
std::unique_lock<std::mutex> guard(_queue_lock);
|
2022-11-30 07:24:09 +08:00
|
|
|
|
|
|
|
_condition_push.wait(guard, [&]() { return _queue.size() < _max_size || !_block; });
|
|
|
|
|
|
|
|
if(_queue.size() == _max_size)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
_queue.push(std::move(item_));
|
|
|
|
}
|
|
|
|
_condition_pop.notify_one();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename... Args>
|
|
|
|
bool
|
|
|
|
emplace(Args&&... args_)
|
|
|
|
{
|
|
|
|
{
|
2023-04-24 11:33:48 +08:00
|
|
|
std::lock_guard<std::mutex> guard(_queue_lock);
|
2022-11-30 07:24:09 +08:00
|
|
|
|
|
|
|
_condition_push.wait(guard, [&]() { return _queue.size() < _max_size || !_block; });
|
|
|
|
|
|
|
|
if(_queue.size() == _max_size)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
_queue.emplace(std::forward<Args>(args_)...);
|
|
|
|
}
|
|
|
|
|
|
|
|
_condition_pop.notify_one();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
pop(T& item_)
|
|
|
|
{
|
|
|
|
{
|
2023-04-24 11:33:48 +08:00
|
|
|
std::unique_lock<std::mutex> guard(_queue_lock);
|
2022-11-30 07:24:09 +08:00
|
|
|
|
|
|
|
_condition_pop.wait(guard, [&]() { return !_queue.empty() || !_block; });
|
|
|
|
if(_queue.empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
item_ = std::move(_queue.front());
|
|
|
|
|
|
|
|
_queue.pop();
|
|
|
|
}
|
|
|
|
|
|
|
|
_condition_push.notify_one();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::size_t
|
|
|
|
size() const
|
|
|
|
{
|
2023-04-24 11:33:48 +08:00
|
|
|
std::lock_guard<std::mutex> guard(_queue_lock);
|
2022-11-30 07:24:09 +08:00
|
|
|
|
|
|
|
return _queue.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
std::size_t
|
|
|
|
capacity() const
|
|
|
|
{
|
|
|
|
return _max_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
empty() const
|
|
|
|
{
|
2023-04-24 11:33:48 +08:00
|
|
|
std::lock_guard<std::mutex> guard(_queue_lock);
|
2022-11-30 07:24:09 +08:00
|
|
|
|
|
|
|
return _queue.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
full() const
|
|
|
|
{
|
2023-04-24 11:33:48 +08:00
|
|
|
std::lock_guard<std::mutex> lock(_queue_lock);
|
2022-11-30 07:24:09 +08:00
|
|
|
|
|
|
|
return (_queue.size() == capacity());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
block()
|
|
|
|
{
|
2023-04-24 11:33:48 +08:00
|
|
|
std::lock_guard<std::mutex> guard(_queue_lock);
|
2022-11-30 07:24:09 +08:00
|
|
|
_block = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
unblock()
|
|
|
|
{
|
|
|
|
{
|
2023-04-24 11:33:48 +08:00
|
|
|
std::lock_guard<std::mutex> guard(_queue_lock);
|
2022-11-30 07:24:09 +08:00
|
|
|
_block = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
_condition_push.notify_all();
|
|
|
|
_condition_pop.notify_all();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
blocking() const
|
|
|
|
{
|
2023-04-24 11:33:48 +08:00
|
|
|
std::lock_guard<std::mutex> guard(_queue_lock);
|
2022-11-30 07:24:09 +08:00
|
|
|
|
|
|
|
return _block;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
mutable std::mutex _queue_lock;
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool _block;
|
|
|
|
std::queue<T> _queue;
|
|
|
|
const std::size_t _max_size;
|
|
|
|
std::condition_variable _condition_push;
|
|
|
|
std::condition_variable _condition_pop;
|
|
|
|
};
|