📄 eatingdlg.cpp
字号:
#ifdef DEBUGING
TRACE("the %d ID is eating\n ",ID);
#endif
m_ph->thinkerStatus[ID] = EATING_STATUS;
m_ph->tropicStatus[(ID + THINKER_NUM -1)%THINKER_NUM] = 1;
m_ph->tropicStatus[ID] = 1;
::InvalidateRect(m_ph->m_view,m_ph->userect[ID],TRUE);
::InvalidateRect(m_ph->m_view,m_ph->Idlerect[ID],TRUE);
::InvalidateRect(m_ph->m_view,m_ph->Idlerect[(ID + THINKER_NUM -1)%THINKER_NUM],TRUE);
::InvalidateRect(m_ph->m_view,m_ph->thinkerRect[ID],TRUE);
Sleep(800 +25*(m_ph->m_speed) + GetRandTime());
//cast the tropic and continue to think
m_ph->thinkerStatus[ID] = THINKING_STATUS;
m_ph->tropicStatus[(ID + THINKER_NUM -1)%THINKER_NUM] = 0;
m_ph->tropicStatus[ID] = 0;
::InvalidateRect(m_ph->m_view,m_ph->userect[ID],TRUE);
::InvalidateRect(m_ph->m_view,m_ph->Idlerect[ID],TRUE);
::InvalidateRect(m_ph->m_view,m_ph->Idlerect[(ID + THINKER_NUM -1)%THINKER_NUM],TRUE);
::InvalidateRect(m_ph->m_view,m_ph->thinkerRect[ID],TRUE);
ReleaseMutex(m_ph->tropics[(ID + THINKER_NUM -1)%THINKER_NUM]);
ReleaseMutex(m_ph->tropics[ID]);
TRACE(" the %d ID is exiting ",ID);
}
m_ph->ThinkerCnt--;
m_ph->thinkerStatus[ID] = NORMAL_STATUS;
::InvalidateRect(m_ph->m_view,m_ph->thinkerRect[ID],TRUE);
if(m_ph->ThinkerCnt == -1)
ResetEvent(m_ph->ThreadExit);
return 1;
}
void CEatingDlg::OnBtnBegin()
{
int i;
if(!m_HasInit)
InitStruct();
m_beginBtn.EnableWindow(FALSE);
m_wndView.m_pthinker=&m_thinker;
m_wndView.OnPaint();
UpdateData();
//先把所有的时间清零
for(i = 0;i<THINKER_NUM;i++)
{
m_thinker.ThinkTime[i]=0;
m_thinker.EatTime[i]=0;
m_thinker.WaitTime[i]=0;
m_thinker.HaveTrop[i]=0;
m_thinker.HaveCur[i]=0;
m_thinker.WaitQueue[i][0]=-1;
m_thinker.HaveFree[i]=0;
m_thinker.WaitBegin[i]=0;
Eat[i].RemoveAll();
Think[i].RemoveAll();
Wait[i].RemoveAll();
}
m_thinker.HaveTrop[1]=2;//因为2和4初始时都占有两个筷子
m_thinker.HaveTrop[3]=2;
Clock=0;
if(m_Strategy==1)
{
int temp_Cus,temp_Trop;
srand( (unsigned)time( NULL ) );
InitList();
m_time++;
m_Process.ResetContent();
m_wndView.m_pthinker=&m_thinker;
CCalendar *p=(CCalendar*)CA_List.GetAt(0);//每次都是取日程表的第一个数
while(CA_List.GetSize()>0&&p->m_Time<m_Clock)
{
CA_List.RemoveAt(0);
Clock=p->m_Time; //走动时钟
temp_Cus=p->m_Customer;
temp_Trop=p->Trop;
if(p->AorD==1)
{
Arrial(temp_Cus,temp_Trop,p);
}
else
{
Departure(temp_Cus,temp_Trop,p);
}
Sleep(m_thinker.m_speed*10);
p=(CCalendar*)CA_List.GetAt(0);
}
Statistic();
m_beginBtn.EnableWindow(TRUE);
}
else
{
if(m_Strategy==2)
{
srand( (unsigned)time( NULL ) );
InitList();
m_time++;
m_Process.ResetContent();
m_wndView.m_pthinker=&m_thinker;
CCalendar *p=(CCalendar*)CA_List.GetAt(0);//每次都是取日程表的第一个数
while(CA_List.GetSize()>0&&p->m_Time<m_Clock)
{
CA_List.RemoveAt(0);
Clock=p->m_Time; //走动时钟
Service(p->m_Customer,p->Trop,p);
Sleep(m_thinker.m_speed*10);
p=(CCalendar*)CA_List.GetAt(0);
}
Statistic();
m_beginBtn.EnableWindow(TRUE);
}
else
{
for(i = 0;i<THINKER_NUM;i++)
{
m_thinker.ThinkerCnt++;
AfxBeginThread(Eating,(PVOID)&m_thinker);
Sleep(50);
}
}
}
m_stopBtn.EnableWindow(TRUE);
//m_beginBtn.EnableWindow(FALSE);
//m_okBtn.EnableWindow(FALSE);
m_HasInit=false;
}
void CEatingDlg::OnBtnStop()
{
SetEvent(m_thinker.ThreadExit);
BeginWaitCursor();
while(WaitForSingleObject(m_thinker.ThreadExit,500) == WAIT_OBJECT_0);
for(int i = 0;i<THINKER_NUM;i++)
CloseHandle(m_thinker.tropics[i]); //初始化MUTEX变量
CloseHandle(m_thinker.ThreadExit);
EndWaitCursor();
m_okBtn.EnableWindow(TRUE);
m_beginBtn.EnableWindow(TRUE);
m_stopBtn.EnableWindow(FALSE);
m_HasInit = FALSE;
}
void CEatingDlg::OnOK()
{
TRACE("%d ",(-1)%5);
CDialog::OnOK();
}
void CEatingDlg::OnDestroy()
{
CDialog::OnDestroy();
font.DeleteObject();
}
void CEatingDlg::OnOutofmemorySlider1(NMHDR* pNMHDR, LRESULT* pResult)
{
*pResult = 0;
}
void CEatingDlg::OnCustomdrawSlider1(NMHDR* pNMHDR, LRESULT* pResult)
{
UpdateData();
m_thinker.m_speed = 100 - m_AdjustSpeed.GetPos();
UpdateData(FALSE);
*pResult = 0;
}
void CEatingDlg::OnButton1()
{
int i,j,t,e,w;
CString str;
m_Result.ResetContent();
if(Think[0].GetSize()>0)
{
for(i=0;i<5;i++)
{
j=Think[i].GetSize();
t=m_thinker.ThinkTime[i];
t=t/j;
j=Eat[i].GetSize();
e=m_thinker.EatTime[i];
e=e/j;
j=Wait[i].GetSize();
w=m_thinker.WaitTime[i];
if(j!=0)
w=w/j;
else
w=0;
str.Format("哲学家 %d 平均思考时间 %2d,平均吃饭时间 %2d,平均等待时间 %2d.",i,t,e,w);
m_Result.AddString(str);
}
}
else
MessageBox("还没有仿真的数据","错误");
}
void CEatingDlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
OnOK();
}
void CEatingDlg::OnBnClickedRadio1()
{
// TODO: 在此添加控件通知处理程序代码
m_Strategy=1;
}
void CEatingDlg::OnBnClickedRadio2()
{
// TODO: 在此添加控件通知处理程序代码
m_Strategy=2;
}
void CEatingDlg::OnBnClickedRadio3()
{
// TODO: 在此添加控件通知处理程序代码
m_Strategy=3;
}
void CEatingDlg::InitList()
{
int temp;
for(int i = 0;i<THINKER_NUM;i++)
{
if(m_thinker.thinkerStatus[i]==THINKING_STATUS)//如果哲学家在思考
{
temp=GetNormalTime(); //获取思考的时间
m_thinker.ThinkTime[i]+=temp;
Think[i].AddTail(temp); //每次思考的时间进入列表,备后面分析使用
CCalendar *p=new CCalendar;
p->m_Time=temp;
p->m_Customer=i; //哲学家只能获取相邻的筷子
p->AorD=1; //表示哲学家要获得这个筷子,进入筷子的队列
p->Trop=(i-1+THINKER_NUM)%THINKER_NUM;//先获取左边的筷子
Add(p);
CCalendar *p1=new CCalendar;//再获右边的
p1->m_Time=temp;
p1->m_Customer=i;
p1->AorD=1;
p1->Trop=i;
Add(p1);
}
else
{
if(m_thinker.thinkerStatus[i]==EATING_STATUS)//如果哲学家在吃饭
{
temp=GetEqualTime();
m_thinker.EatTime[i]+=temp;
Eat[i].AddTail(temp); //每次吃饭的时间加入到用餐的列表中,备后面分析使用
CCalendar *p=new CCalendar;
p->m_Time=temp;
p->m_Customer=i;
p->AorD=0; //表示哲学家吃完要释放筷子
p->Trop=(i-1+THINKER_NUM)%THINKER_NUM;//先释放左边的筷子
Add(p);
CCalendar *p1=new CCalendar;//再释放右边的筷子
p1->m_Time=temp;
p1->m_Customer=i;
p1->AorD=0;
p1->Trop=i;
Add(p1);
}
}
}
}
void CEatingDlg::Add(CCalendar *p)//按照时间顺序添加到日程表中
{
CCalendar *ptemp;
CA_List.Add((CCalendar*)p);
int m_Size=CA_List.GetSize();
int i;
for(i=m_Size-1;i>0;i--)
{
ptemp=(CCalendar*)CA_List.GetAt(i-1);
if(ptemp->m_Time>p->m_Time)
{
CA_List.SetAt(i,(CCalendar*)ptemp);
}
else
{
CA_List.SetAt(i,(CCalendar*)p);
break;
}
}
if(i==0)
CA_List.SetAt(i,(CCalendar*)p);
}
void CEatingDlg::Arrial(int i,int j,CCalendar *p)
{
CString str;//在进度栏里加入事件
if(m_thinker.tropicStatus[j]==0) //如果筷子是空闲的
{
m_thinker.HaveTrop[i]++;
if(m_thinker.HaveTrop[i]==2)
{
int temp=GetEqualTime();//吃饭时间服从均匀分布
m_thinker.EatTime[i]+=temp;
Eat[i].AddTail(temp); //每次吃饭的时间加入到用餐的列表中,备后面分析使用
m_thinker.thinkerStatus[i]=EATING_STATUS;
m_thinker.tropicStatus[j]=1;//筷子不再是空闲的
//开始吃饭意味着等待就结束
int temp1;
if(m_thinker.WaitBegin[i]!=0)
{
temp1=p->m_Time-m_thinker.WaitBegin[i];
m_thinker.WaitTime[i]+=temp1;
Wait[i].AddTail(temp1); // 每次等待的时间加入到等待列表中,备后面分析使用
m_thinker.WaitBegin[i]=0 ;//重新回到初值
}
str.Format("时刻: %4d 哲学家 %d 获取筷子 %d 成功,开始吃饭!",p->m_Time,p->m_Customer,p->Trop);
m_Process.InsertString(0,str);
m_Process.RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
::InvalidateRect(m_thinker.m_view,m_thinker.userect[i],TRUE);
::InvalidateRect(m_thinker.m_view,m_thinker.Idlerect[i],TRUE);
::InvalidateRect(m_thinker.m_view,m_thinker.Idlerect[(i + THINKER_NUM -1)%THINKER_NUM],TRUE);
::InvalidateRect(m_thinker.m_view,m_thinker.thinkerRect[i],TRUE);
m_wndView.OnPaint();
CCalendar *p1=new CCalendar; //吃完饭要调度释放筷子的事件
p1->m_Time=p->m_Time+temp;
p1->m_Customer=i;
p1->Trop=(i-1+THINKER_NUM)%THINKER_NUM;
p1->AorD=0;
Add(p1);
CCalendar *p2=new CCalendar; //右边的
p2->m_Time=p->m_Time+temp;
p2->m_Customer=i;
p2->Trop=i;
p2->AorD=0;
Add(p2);
}
else
{
int l;
if(p->m_Customer==j)
l=(p->m_Customer+4)%5;
else
l=p->m_Customer;
m_thinker.tropicStatus[j]=1;//筷子不再是空闲的
if(m_thinker.WaitBegin[i]==0) //如果还没有等待的话在这个时刻开始等待
m_thinker.WaitBegin[i]=p->m_Time;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -