www.pudn.com > p_eating.rar > eatingDlg.cpp
// eatingDlg.cpp : implementation file
//
#include "stdafx.h"
#include "eating.h"
#include "eatingDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define DEBUGING
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
#include "math.h"
#include "SpecialDlg.h"
#include ".\eatingdlg.h"
extern CPoint ta5[5]; //定义五个变量表示哲学家所在位置
extern CPoint tropic5[5];
extern CPoint usetropic[5];
extern int radius;
extern CPoint CenterPoint;
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CEatingDlg dialog
CEatingDlg::CEatingDlg(CWnd* pParent /*=NULL*/)
: CDialog(CEatingDlg::IDD, pParent)
, m_Clock(0)
{
//{{AFX_DATA_INIT(CEatingDlg)
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CEatingDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CEatingDlg)
DDX_Control(pDX, IDC_SLIDER1, m_AdjustSpeed);
DDX_Control(pDX, IDOK, m_okBtn);
DDX_Control(pDX, IDC_BTN_STOP, m_stopBtn);
DDX_Control(pDX, IDC_BTN_BEGIN, m_beginBtn);
DDX_Control(pDX, IDC_STATIC_VIEW, m_wndView);
//}}AFX_DATA_MAP
DDX_Control(pDX, IDC_RADIO1, m_Strategy1);
DDX_Control(pDX, IDC_LIST1, m_Process);
DDX_Text(pDX,IDC_EDIT1,m_Clock);
DDX_Control(pDX, IDC_LIST2, m_Result);
}
BEGIN_MESSAGE_MAP(CEatingDlg, CDialog)
//{{AFX_MSG_MAP(CEatingDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BTN_BEGIN, OnBtnBegin)
ON_BN_CLICKED(IDC_BTN_STOP, OnBtnStop)
ON_WM_DESTROY()
ON_NOTIFY(NM_OUTOFMEMORY, IDC_SLIDER1, OnOutofmemorySlider1)
ON_NOTIFY(NM_CUSTOMDRAW, IDC_SLIDER1, OnCustomdrawSlider1)
ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDOK, OnBnClickedOk)
ON_BN_CLICKED(IDC_RADIO1, OnBnClickedRadio1)
ON_BN_CLICKED(IDC_RADIO2, OnBnClickedRadio2)
ON_BN_CLICKED(IDC_RADIO3, OnBnClickedRadio3)
ON_BN_CLICKED(IDC_BUTTON2, OnBnClickedButton2)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CEatingDlg message handlers
BOOL CEatingDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
pSysMenu->EnableMenuItem(SC_CLOSE,MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
m_Strategy=1;
m_Strategy1.SetCheck(1);
Clock=0; //全局时钟清零
InitStruct(); //初始化结构体
m_thinker.m_speed = 20;
m_wndView.SetThinkersInfo(&m_thinker);
m_wndView.SetGradientColor(RGB(0,0,0));
font.CreatePointFont(160,"华文行楷");
m_wndView.SetFont(&font);
m_AdjustSpeed.SetRange(0,100);
m_AdjustSpeed.SetPos(80);
//m_AdjustSpeed.SetTic(10);
m_AdjustSpeed.SetTicFreq(200);
// TODO: Add extra initialization here
CRect rect;
int i;
radius = 160;
m_wndView.GetClientRect(&rect);
CenterPoint = rect.CenterPoint();
for(i = 0;i<5;i++)
{
ta5[i] = CPoint(radius*cos((90 + i*72)*3.141526/180),
radius*sin((90 + i*72)*3.141526/180));
ta5[i].x += CenterPoint.x;
ta5[i].y = CenterPoint.y - ta5[i].y;
}
for(i = 0;i<5;i++)
{
tropic5[i] = CPoint((radius-10)*cos((126 + i*72)*3.1415926/180),
(radius-10)*sin((126 + i*72)*3.1415926/180));
tropic5[i].x += CenterPoint.x;
tropic5[i].y = CenterPoint.y - tropic5[i].y;
}
for(i = 0;i<5;i++)
{
usetropic[i] = CPoint((radius-10)*cos((90 + i*72)*3.141526/180),
(radius-10)*sin((90 + i*72)*3.141526/180));
usetropic[i].x += CenterPoint.x;
usetropic[i].y = CenterPoint.y - usetropic[i].y;
}
m_thinker.thinkerRect[0].SetRect(ta5[0].x,ta5[0].y - 60,
ta5[0].x,ta5[0].y - 60);
m_thinker.thinkerRect[0].InflateRect(60,20);
m_thinker.thinkerRect[1].SetRect(ta5[1].x-85,ta5[1].y,
ta5[1].x-85,ta5[1].y);
m_thinker.thinkerRect[1].InflateRect(60,20);
m_thinker.thinkerRect[2].SetRect(ta5[2].x-20,ta5[2].y+50,
ta5[2].x-20,ta5[2].y+50);
m_thinker.thinkerRect[2].InflateRect(60,20);
m_thinker.thinkerRect[3].SetRect(ta5[3].x+10,ta5[3].y+50,
ta5[3].x+10,ta5[3].y+50);
m_thinker.thinkerRect[3].InflateRect(60,20);
m_thinker.thinkerRect[4].SetRect(ta5[4].x+85,ta5[4].y,
ta5[4].x+85,ta5[4].y);
m_thinker.thinkerRect[4].InflateRect(60,20);
m_stopBtn.EnableWindow(FALSE);
m_HasInit = TRUE;
m_time=0; //运行次数与重复删除法相关
for(int k=0;k<5;k++)
{
Total_Think[k]=0;
Total_Eat[k]=0;
Total_Wait[k]=0;
}
return TRUE; // return TRUE unless you set the focus to a control
}
void CEatingDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CEatingDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CEatingDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CEatingDlg::InitStruct()
{
m_thinker.thinkerStatus[0] = THINKING_STATUS;
m_thinker.tropics[0] = CreateMutex(NULL,FALSE,NULL); //初始化MUTEX变量
m_thinker.tropicStatus[0] = 1; //筷子空闲
m_thinker.thinkerStatus[1] = EATING_STATUS;
m_thinker.tropics[1] = CreateMutex(NULL,FALSE,NULL); //初始化MUTEX变量
m_thinker.tropicStatus[1] = 1; //筷子空闲
m_thinker.thinkerStatus[2] = THINKING_STATUS;
m_thinker.tropics[2] = CreateMutex(NULL,FALSE,NULL); //初始化MUTEX变量
m_thinker.tropicStatus[2] = 1; //筷子空闲
m_thinker.thinkerStatus[3] = EATING_STATUS;
m_thinker.tropics[3] = CreateMutex(NULL,FALSE,NULL); //初始化MUTEX变量
m_thinker.tropicStatus[3] = 1; //筷子空闲
m_thinker.thinkerStatus[4] = THINKING_STATUS;
m_thinker.tropics[4] = CreateMutex(NULL,FALSE,NULL); //初始化MUTEX变量
m_thinker.tropicStatus[4] = 0; //筷子空闲
m_thinker.m_view = m_wndView.GetSafeHwnd();
m_thinker.ThinkerCnt = -1;
m_thinker.ThreadExit = CreateEvent(NULL,TRUE,FALSE,NULL); //初始化为没有被使用,可用
}
int GetRandTime(void)
{
srand((unsigned)time(NULL));
return rand()%500;
}
UINT Eating(PVOID pParam)
{
pThinkers m_ph = (pThinkers)pParam;
int ID = m_ph->ThinkerCnt;
while(WaitForSingleObject(m_ph->ThreadExit,0) != WAIT_OBJECT_0)
{
// Thinking
#ifdef DEBUGING
TRACE("the %d ID is thinking\n ",ID);
#endif
//::InvalidateRgn(m_ph->m_view,m_ph->rect,TRUE);
m_ph->thinkerStatus[ID] = THINKING_STATUS;
int m=GetRandTime();
Sleep(800 + 20*(m_ph->m_speed) + m);
//hungry
#ifdef DEBUGING
TRACE("the %d ID is hungry \n",ID);
#endif
m_ph->thinkerStatus[ID] = HUNGRY_STATUS;
::InvalidateRect(m_ph->m_view,m_ph->thinkerRect[ID],TRUE);
while(TRUE)
{
if(WaitForSingleObject(m_ph->tropics[(ID + THINKER_NUM -1)%THINKER_NUM],60+GetRandTime()) == WAIT_OBJECT_0) //得到了左边的筷子
{
if(WaitForSingleObject(m_ph->tropics[ID],100) != WAIT_OBJECT_0)
ReleaseMutex(m_ph->tropics[(ID + THINKER_NUM -1)%THINKER_NUM]);//如果没有得到右边的筷子,就释放自己获得的左边的筷子,等待
else
break;
}
Sleep(600 + 10*(m_ph->m_speed)+GetRandTime());
}
//begin to eating
#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;i0&&p->m_Timem_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_Timem_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;i0)
{
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;im_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;
str.Format("时刻: %4d 哲学家 %d 获取筷子 %d 成功,等待筷子 %d",p->m_Time,p->m_Customer,p->Trop,l);
m_Process.InsertString(0,str);
m_Process.RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
m_thinker.thinkerStatus[i]=HUNGRY_STATUS;
::InvalidateRect(m_thinker.m_view,m_thinker.thinkerRect[i],TRUE);
m_wndView.OnPaint();
}
}
else
{
if(m_thinker.WaitBegin[i]==0) //如果还没有等待的话在这个时刻开始等待
m_thinker.WaitBegin[i]=p->m_Time;
str.Format("时刻: %4d 哲学家 %d 获取筷子 %d 不成功,开始等待筷子 %d",p->m_Time,p->m_Customer,p->Trop,p->Trop);
m_Process.InsertString(0,str);
m_Process.RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
m_thinker.thinkerStatus[i]=HUNGRY_STATUS;
::InvalidateRect(m_thinker.m_view,m_thinker.thinkerRect[i],TRUE);
m_wndView.OnPaint();
m_thinker.WaitQueue[j][m_thinker.HaveCur[j]]=i;
m_thinker.HaveCur[j]++;//代表等待队列的长度
}
}
void CEatingDlg::Departure(int i,int j,CCalendar *p)
{
m_thinker.tropicStatus[j]=0; //释放筷子资源
if(m_thinker.WaitQueue[j][0]>=0) //如果有哲学家在等待这个筷子,那么调度这个哲学家来取
{
CCalendar *p2=new CCalendar; //加进日程表给等待的哲学家
p2->m_Time=p->m_Time;
p2->m_Customer=m_thinker.WaitQueue[j][0];
p2->Trop=j;
p2->AorD=1;
Add(p2);
if(m_thinker.HaveCur[j]==2)
{
m_thinker.WaitQueue[j][0]=m_thinker.WaitQueue[j][1];
}
else
m_thinker.WaitQueue[j][0]=-1; //恢复初始值
m_thinker.HaveCur[j]--;
}
int temp=GetNormalTime(); //思考时间服从正态分布
m_thinker.ThinkTime[i]+=temp;
Think[i].AddTail(temp); //每次思考的时间进入列表,备后面分析使用
m_thinker.thinkerStatus[i]=THINKING_STATUS;
::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();
m_thinker.HaveTrop[i]--;
m_thinker.HaveFree[i]++;
if(m_thinker.HaveFree[i]==2)//当两个都释放后
{
CCalendar *p1=new CCalendar;//调度下次i再来要j的时间,也就是思考完的时间
p1->m_Time=p->m_Time+temp;
p1->m_Customer=i;
p1->Trop=(i-1+THINKER_NUM)%THINKER_NUM;
p1->AorD=1;
Add(p1);
CCalendar *p3=new CCalendar;//再获右边的
p3->m_Time=p->m_Time+temp;
p3->m_Customer=i;
p3->Trop=i;
p3->AorD=1;
Add(p3);
m_thinker.HaveFree[i]=0;//复原已释放的资源数目
}
CString str;//在进度栏里加入事件
if(m_thinker.HaveTrop[i]==0)
str.Format("时刻: %4d 哲学家 %d 释放筷子 %d 开始思考!",p->m_Time,p->m_Customer,p->Trop);
else
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);
}
void CEatingDlg::Arrial2(int i,int j,CCalendar *p)
{
int temp=GetNormalTime(); //思考时间服从正态分布
m_thinker.ThinkTime[i]+=temp;
Think[i].AddTail(temp); //每次思考的时间进入列表,备后面分析使用
m_thinker.thinkerStatus[i]=THINKING_STATUS;
m_thinker.tropicStatus[j]=0;//释放完后筷子变为空闲
::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();
m_thinker.HaveTrop[i]--; //拥有的筷子数减一
m_thinker.HaveFree[i]++;
if(m_thinker.HaveFree[i]==2)//当两个都释放后
{
CCalendar *p1=new CCalendar;//调度下次i再来要j的时间,也就是思考完的时间
p1->m_Time=p->m_Time+temp;
p1->m_Customer=i;
p1->Trop=(i-1+THINKER_NUM)%THINKER_NUM;
p1->AorD=1;
Add(p1);
CCalendar *p3=new CCalendar;//再获右边的
p3->m_Time=p->m_Time+temp;
p3->m_Customer=i;
p3->Trop=i;
p3->AorD=1;
Add(p3);
m_thinker.HaveFree[i]=0;//复原已释放的资源数目
}
CString str;//在进度栏里加入事件
if(m_thinker.HaveTrop[i]==0)
str.Format("时刻: %4d 哲学家 %d 释放筷子 %d 开始思考!",p->m_Time,p->m_Customer,p->Trop);
else
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);
}
void CEatingDlg::Departure2(int i,int j,CCalendar *p)
{
CString str;
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);
}
void CEatingDlg::Service(int i,int j,CCalendar *p)
{
int que;
CString str;
if(p->AorD) //判断哲学家是取筷子用餐还是用完餐释放筷子
{
if((m_thinker.tropicStatus[j]==0)&&(m_thinker.WaitQueue[j][0]>=0))//如果j空闲且它的排队不空
{
que=m_thinker.WaitQueue[j][0]; //取出排在前面的哲学家
if(m_thinker.HaveCur[j]==2) //如果有两个哲学家在等待j
{
m_thinker.WaitQueue[j][0]=m_thinker.WaitQueue[j][1];//移出第一个哲学家
m_thinker.WaitQueue[j][1]=-1;
}
else
{
m_thinker.WaitQueue[j][0]=-1; //如果只有一个哲学家在等待,就移出这个哲学家
}
m_thinker.HaveCur[j]--;
m_thinker.HaveTrop[que]++; //如果que这个哲学家已经获得两个筷子了就调动departure
if(m_thinker.HaveTrop[que]==2)
{
Departure2(que,j,p);
}
else
{
int l;
if(que==j)
l=(que+4)%5;
else
l=que;
if(m_thinker.WaitBegin[que]==0) //如果还没有等待的话在这个时刻开始等待
m_thinker.WaitBegin[que]=p->m_Time;
str.Format("时刻: %4d 哲学家 %d 获取筷子 %d 成功,等待筷子 %d",p->m_Time,que,j,l);
m_Process.InsertString(0,str);
m_Process.RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
m_thinker.thinkerStatus[que]=HUNGRY_STATUS;
::InvalidateRect(m_thinker.m_view,m_thinker.thinkerRect[que],TRUE);
m_wndView.OnPaint();
}
}
else
{
if(m_thinker.tropicStatus[j]==0) //如果筷子是空闲的
{
m_thinker.HaveTrop[i]++;
if(m_thinker.HaveTrop[i]==2)
{
Departure2(i,j,p);
}
else
{
int l;
if(p->m_Customer==j)
l=(p->m_Customer+4)%5;
else
l=p->m_Customer;
if(m_thinker.WaitBegin[i]==0) //如果还没有等待的话在这个时刻开始等待
m_thinker.WaitBegin[i]=p->m_Time;
str.Format("时刻: %4d 哲学家 %d 获取筷子 %d 成功,等待筷子 %d",p->m_Time,p->m_Customer,p->Trop,l);
m_Process.InsertString(0,str);
m_Process.RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
m_thinker.thinkerStatus[i]=HUNGRY_STATUS;
::InvalidateRect(m_thinker.m_view,m_thinker.thinkerRect[i],TRUE);
m_wndView.OnPaint();
m_thinker.tropicStatus[j]=1;//筷子不再是空闲的
}
}
else //表明筷子不空而它的等待队列是空的
{
if(m_thinker.WaitBegin[i]==0) //如果还没有等待的话在这个时刻开始等待
m_thinker.WaitBegin[i]=p->m_Time;
str.Format("时刻: %4d 哲学家 %d 获取筷子 %d 不成功,开始等待筷子 %d",p->m_Time,p->m_Customer,p->Trop,p->Trop);
m_Process.InsertString(0,str);
m_Process.RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
m_thinker.thinkerStatus[i]=HUNGRY_STATUS;
::InvalidateRect(m_thinker.m_view,m_thinker.thinkerRect[i],TRUE);
m_wndView.OnPaint();
m_thinker.WaitQueue[j][m_thinker.HaveCur[j]]=i;
m_thinker.HaveCur[j]++;//代表等待队列的长度
}
}
}
else //表明哲学家是用完餐释放筷子
{
if((m_thinker.WaitQueue[j][0]>=0)) //如果筷子的等待队列不是空的
{
CCalendar *p2=new CCalendar; //加进日程表给等待的哲学家
p2->m_Time=p->m_Time;
p2->m_Customer=m_thinker.WaitQueue[j][0];
p2->Trop=j;
p2->AorD=1;
Add(p2);
if(m_thinker.HaveCur[j]==2)
{
m_thinker.WaitQueue[j][0]=m_thinker.WaitQueue[j][1];
}
else
m_thinker.WaitQueue[j][0]=-1; //恢复初始值
m_thinker.HaveCur[j]--;
}
else
{
m_thinker.tropicStatus[j]=0;//i释放了j,j空闲
}
Arrial2(i,j,p);
}
}
int CEatingDlg::GetNormalTime()
{
float m_u1,m_u2,m_x1;
m_u1=(float)rand()/0x7fff;
m_u1=(float)rand()/0x7fff;
m_u2=(float)rand()/0x7fff;
float v1=2*m_u1-1;
float v2=2*m_u2-1;
float W=v1*v1+v2*v2;
if(W<1)
{
m_x1=v1*sqrt(((-2)*log(W))/W);
m_x1=10+m_x1*sqrt((double)8);
return (int)m_x1;
}
else
return 10;
}
int CEatingDlg::GetEqualTime()
{
int m;
m=rand()%11;
m=m+15;
return m;
}
void CEatingDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
CString str;
int t,e,w;
if(m_time>0)
{
m_Result.ResetContent();
str.Format("共进行了 %d 次仿真:",m_time);
m_Result.AddString(str);
for(int i=0;i<5;i++)
{
t=Total_Think[i]/m_time;
e=Total_Eat[i]/m_time;
w=Total_Wait[i]/m_time;
str.Format("哲学家 %d 平均思考时间 %2d,平均吃饭时间 %2d,平均等待时间 %2d.",i,t,e,w);
m_Result.AddString(str);
}
}
else
MessageBox("没有仿真数据","错误");
}
void CEatingDlg::Statistic()
{
int i,j,t,e,w;
for(i=0;i<5;i++)
{
j=Think[i].GetSize();
t=m_thinker.ThinkTime[i];
if(j!=0)
t=t/j;
else
t=0;
Total_Think[i]+=t;
j=Eat[i].GetSize();
e=m_thinker.EatTime[i];
if(j!=0)
e=e/j;
else
e=0;
Total_Eat[i]+=e;
j=Wait[i].GetSize();
w=m_thinker.WaitTime[i];
if(j!=0)
w=w/j;
else
w=0;
Total_Wait[i]+=w;
}
}