公平队列的实现
(金庆的专栏)
公平队列(Fair Queuing)是一种调度算法,与先进先出队列不同,
公平队列分成几个子队列,每个子队列公平地得到处理。
例如上海地铁站充值窗口有两个,一个站外,一个站内,由同一位服务人员受理,
服务人员会轮流处理两个窗口的请求,两个窗口的队列将公平地得到处理。
公平队列应用于路由器,保证不同的数据流得到公平处理。
Zeromq的消息处理也应用了公平队列,不会因为高数据量的连接阻塞其他连接的处理。
在网游服务器中,公平队列应用于消息的处理,解决场景局部拥挤造成整服都卡的问题。
例如消息处理按地图排队,这样某个地图的消息拥塞不会影响其他地图的消息处理。
fair_queue 仿 std::priority_queue 实现
(金庆的专栏)
公平队列(Fair Queuing)是一种调度算法,与先进先出队列不同,
公平队列分成几个子队列,每个子队列公平地得到处理。
例如上海地铁站充值窗口有两个,一个站外,一个站内,由同一位服务人员受理,
服务人员会轮流处理两个窗口的请求,两个窗口的队列将公平地得到处理。
公平队列应用于路由器,保证不同的数据流得到公平处理。
Zeromq的消息处理也应用了公平队列,不会因为高数据量的连接阻塞其他连接的处理。
在网游服务器中,公平队列应用于消息的处理,解决场景局部拥挤造成整服都卡的问题。
例如消息处理按地图排队,这样某个地图的消息拥塞不会影响其他地图的消息处理。
fair_queue 仿 std::priority_queue 实现
/* Fair queue gives each sub queue a fair share.
Author: Jin Qing ( http://blog.csdn.net/jq0123 )
Example:
fair_queue<int, int> fq;
fq.push(1, 11);
fq.push(1, 12);
fq.push(1, 13);
fq.push(2, 21);
VERIFY(11 == fq.top()); fq.pop();
VERIFY(21 == fq.top()); fq.pop();
VERIFY(12 == fq.top()); fq.pop();
VERIFY(13 == fq.top()); fq.pop();
*/
#ifndef _FAIR_QUEUE_H_
#define _FAIR_QUEUE_H_
#include <queue>
#include <boost/assert.hpp>
#include <boost/unordered_map.hpp>
// TEMPLATE CLASS fair_queue
template<class _Kty, class _Ty>
class fair_queue
{
public:
typedef _Kty key_type;
typedef _Ty value_type;
protected:
typedef std::queue<velue_type> sub_queue_type;
typedef boost::unordered_map<key_type, sub_queue_type> map_type;
typedef std::queue<sub_queue_type *> ordered_queue_type;
typedef boost::unordered_map<sub_queue_type *, key_type> reversed_map_type;
public:
fair_queue() {};
bool empty() const
{ // test if queue is empty
return m.empty();
}
const value_type & top() const
{ // return top element
BOOST_ASSERT(!empty());
BOOST_ASSERT(q.front());
return q.front()->front();
}
value_type top()
{ // return mutable top element
BOOST_ASSERT(!empty());
BOOST_ASSERT(q.front());
return q.front()->front();
}
void push(const key_type & k, const value_type & v)
{ // insert value in k sub queue
map_type::iterator itr = m.find(k);
if (itr != m.end())
{
BOOST_ASSERT(!(*itr).second.empty());
(*itr).second.push(v);
return;
}
// new sub queue
sub_queue_type * sub_queue = &m[k];
sub_queue->push(v);
BOOST_ASSERT(1 == sub_queue->size());
q.push(sub_queue);
rm[sub_queue] = k;
BOOST_ASSERT(q.size() == rm.size());
BOOST_ASSERT(m.size() == q.size());
}
void pop()
{ // erase top element
BOOST_ASSERT(!empty());
BOOST_ASSERT(!q.empty());
sub_queue_type * sub_queue = q.front();
q.pop();
BOOST_ASSERT(sub_queue);
sub_queue->pop();
if (!sub_queue->empty())
{
// move to the end
q.push(sub_queue);
return;
}
// erase empty sub queue
const key_type & k = rm[sub_queue];
m.erase(k);
rm.erase(sub_queue);
BOOST_ASSERT(q.size() == rm.size());
BOOST_ASSERT(m.size() == q.size())
}
protected:
map_type m; //container
ordered_queue_type q; // to order the queues
reversed_map_type rm; // to delete key in m
};
#endif // _FAIR_QUEUE_H_