// sync_case.h
#ifndef SYNC_CASE_UWINB_200810291954
#define SYNC_CASE_UWINB_200810291954
#include <afxmt.h>
#include <iostream>
/*
利用数组实现循环队列,队空想出队时或队满想入队时会阻塞
同一时刻只能有一个入队操作,同一时刻只能有一个出队操作
入队和出队操作可以同时进行,无需同步也不会互相干扰
模板参数 N 是队列可容纳的最大元素数目
*/
template<class T, int N>
class sync_queue
{
public:
sync_queue():pos_in(0), pos_out(0), objs_in(N,N), objs_out(0,N)
{
}
/*
sync_queue(sync_queue const &obj) // 拷贝构造函数
{
memcpy(elem, obj.elem, sizeof(obj.elem));
pos_in = obj.pos_in;
pos_out = obj.pos_out;
// 同步对象如何初始化?
}
*/
protected:
virtual ~sync_queue() // 通过指针动态访问时需要执行子类的析构函数
{
//if ( != NULL) delete
}
public:
void push(T const &t)
{
static CCriticalSection objcs_in;
objcs_in.Lock();
objs_in.Lock();
elem[pos_in] = t;
pos_in = next(pos_in);
objs_out.Unlock();
objcs_in.Unlock();
}
T const &pop() // 和push()同时执行时,在队空时可能有误判
{
static CCriticalSection objcs_out;
objcs_out.Lock();
objs_out.Lock();
int pos_cur = pos_out;
pos_out = next(pos_out);
objs_in.Unlock();
objcs_out.Unlock();
return elem[pos_cur];
}
/*
sync_queue &operator=(sync_queue const &obj) // 重载赋值运算符
{
if (*this != obj)
{
// 没有动态申请资源需要释放
}
return *this;
}
*/
friend std::ostream &operator<<(std::ostream &out, sync_queue const &obj);
private:
int next(int pos) const // 循环数组中计算下一个偏移位置
{
return (pos+1) % (N+1);
}
T elem[N+1]; // 多加一个占位元素用以区分队空和队满
int pos_in; // 待入队偏移
int pos_out; // 将出队偏移
CSemaphore objs_in; //入队信号量计数,队满时阻塞
CSemaphore objs_out; //出队信号量计数,队空时阻塞
};
template<class T, int N>
std::ostream &operator<<(std::ostream &out, sync_queue<T,N> const &obj)
{
static CCriticalSection objcs_see; // 不同类对象之间也需要同步,确保每次输出的完整性
static int i=0;
objcs_see.Lock();
#ifdef _DEBUG
out<<"{in="<<obj.pos_in<<", out="<<obj.pos_out<<", all=[";
for (i=0; i<N+1; ++i) out<<obj.elem[i]<<", "; out<<"#]; "<<std::ends;
#else
out<<'{';
#endif
// 从出队偏移到入队偏移自左向右输出队列有效值元素序列
out<<"val=[";
for (i=obj.pos_out; i!=obj.pos_in; i=obj.next(i)) out<<obj.elem[i]<<", "; out<<"#]}"<<std::flush;
objcs_see.Unlock();
return out;
}
#endif // SYNC_CASE_UWINB_200810291954