概述
有时我们的服务会从多个其他子服务接收请求,不同类型的请求频率相差比较大,如果采用一个集中的队列,对到来的各个请求排队分发处理,则会出现繁忙的请求占据了队列的大部分,比较闲的请求到达后排在队尾,很长时间才会得到处理机会,出现不必要的延迟加大。这种情况下如果要加强各类型请求的响应及时性,可以采用优先队列,按照请求类型的频率加预计排队时间指定优先级,也可以使用公平队列,公平地处理各个类型的消息。
完全公平队列的原理很简单:为各个类型请求维护一个单独的子队列,维护一个链表包含所有子队列的指针;接收到请求后,根据类型找到其子队列并插入子队列末尾;分发线程分发请求时,依次遍历链表中的子队列并将此子队列移动到链表尾,如果子队列有请求,则将请求投递到工作线程执行,否则一直遍历,直到链表中的所有子队列都查询过,如果还是没有请求待处理,则进入等待。
按照上面描述,可以如下实现:unordered_map 用来保存类型和对应的子队列,list 维护着子队列的指针用来遍历。
#ifndef __COMPLETE_FAIR_QUEUE_H_
#define __COMPLETE_FAIR_QUEUE_H_
#include <list>
#include <unordered_map>
#include <mutex>
#include <condition_variable>
template <
class _Key,
class _Val,
class _Hash = std::hash<_Key>,
class _Pred = std::equal_to<_Key> >
class cfq
{
using sub_queue = std::list<_Val>;
using sub_queues = std::unordered_map<_Key, sub_queue, _Hash, _Pred>;
using trival_queues = std::list<sub_queue*>;
public:
cfq() = default;
~cfq() = default;
void erase(const _Key &key)
{
std::unique_lock<std::mutex> ulk(mut_);
auto _it = sub_queues_.find(key);
if (_it == sub_queues_.end())
return;
erase_from_trival_queues(&(_it->second));
sub_queues_.erase(_it);
}
void push(const _Key &key, const _Val &val)
{
std::unique_lock<std::mutex> ulk(mut_);
auto _it = sub_queues_.find(key);
if (_it == sub_queues_.end())
{
sub_queue _sub_queue{};
_sub_queue.push_back(val);
auto _rit = sub_queues_.insert(std::make_pair(key, std::move(_sub_queue)));
trival_queues_.push_back(&(_rit.first->second));
}
else
_it->second.push_back(val);
cond_.notify_one();
}
_Val wait_and_pop()
{
std::unique_lock<std::mutex> ulk(mut_);
do
{
auto sub_queue_size = trival_queues_.size();
for (decltype(sub_queue_size) idx = 0; idx < sub_queue_size; ++idx)
{
auto _sub_queue = trival_queues_.front();
trival_queues_.pop_front();
trival_queues_.push_back(_sub_queue);
if (!_sub_queue->empty())
{
auto _val = _sub_queue->front();
_sub_queue->pop_front();
return _val;
}
}
cond_.wait(ulk);
} while (1);
}
bool try_pop(_Val &val)
{
std::unique_lock<std::mutex> ulk(mut_);
auto sub_queue_size = trival_queues_.size();
for (decltype(sub_queue_size) idx = 0; idx < sub_queue_size; ++idx)
{
auto _sub_queue = trival_queues_.front();
trival_queues_.pop_front();
trival_queues_.push_back(_sub_queue);
if (!_sub_queue->empty())
{
val = _sub_queue->front();
_sub_queue->pop_front();
return true;
}
}
return false;
}
private:
void erase_from_trival_queues(sub_queue *_sub_queue)
{
for (auto _it = trival_queues_.begin(); _it != trival_queues_.end(); ++_it)
{
if (*_it == _sub_queue)
{
trival_queues_.erase(_it);
break;
}
}
}
private:
std::mutex mut_;
std::condition_variable cond_;
sub_queues sub_queues_;
trival_queues trival_queues_;
};
#endif //__COMPLETE_FAIR_QUEUE_H_
最后
以上就是紧张啤酒为你收集整理的c++11 完全公平队列实现的全部内容,希望文章能够帮你解决c++11 完全公平队列实现所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复