映射队列有4个API,分成两对。分别是:
template<typename Fuck>
BoundedMappingQueue
{
public:
Fuck* Get();
void Push();
Fuck* Pop(int *pos);
void Put(int pos);
};
其中Get和Push由用户调用,Pop和Put由线程池调用。
// 用户
Fuck *shit = queue.Get();
// 对shit进行初始化或赋值
// 初始化或赋值需要快
// 因为此时队列处于加锁状态
queue.Push();
// 线程池
int pos;
Fuck *shit = queue.Pop(&pos);
(*shit)();// 干活
queue.Put(pos);
具体介绍映射队列的每个API。
template<typename Fuck>
Fuck* Get()
{
mutex_.Lock();
// 等待空闲的元素
while (avail_[front_] < 0)
empty_.Wait(mutex_);
return queue_[avail_[front_]];
// 不解锁,因为我们对参数进行初始化
// 后会立刻调用Push
}
template<typename Fuck>
void Push()
{
// 将初始化完毕的参数位置传给工作槽
work_[front_] = avail_[front_];
// 从空闲槽将元素位置删除
avail_[front_] = -1;
if (++front_ == capacity_)
front_ = 0;
mutex_.Unlock();
// 唤醒工作线程
ready_.Signal();
}
template<typename Fuck>
Fuck* Pop(int *pos)
{
mutex_.Lock();
// 等待可以工作的元素
while (work_[work_back_] < 0)
ready_.Wait(mutex_);
// 获取可以工作的元素位置并保存于pos
// 我们需要保存pos因为在完成工作后
// 需要将元素位置重新放入空闲槽
*pos = work_[work_back_];
Fuck *shit = queue_[*pos];
// 从工作槽中将元素位置删除
work_[work_back_] = -1;
if (++work_back_ == capacity_)
work_back_ = 0;
mutex_.Unlock();
return shit;
}
template<typename T>
void Put(int pos)
{
mutex_.Lock();
// 将空闲元素的位置放入空闲槽
avail_[avail_back_] = pos;
if (++avail_back_ == capacity_)
avail_back_ = 0;
mutex_.Unlock();
// 唤醒入列线程
empty_.Signal();
}