?? philosopherview.cpp
字號:
// PhilosopherView.cpp : implementation of the CPhilosopherView class
//
#include "stdafx.h"
#include "Philosopher.h"
#include "PhilosopherDoc.h"
#include "PhilosopherView.h"
#include "math.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
BOOL chopSticks[PHIL_NUM] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
BOOL Finished[PHIL_NUM] ={TRUE, TRUE, TRUE, TRUE, TRUE, TRUE};
CMutex *m_pMutex = NULL;
CEvent *m_pEvent = NULL;
UINT DineOnce(LPVOID pParam);
UINT DineMany(LPVOID pParam);
/////////////////////////////////////////////////////////////////////////////
// CPhilosopherView
IMPLEMENT_DYNCREATE(CPhilosopherView, CView)
BEGIN_MESSAGE_MAP(CPhilosopherView, CView)
//{{AFX_MSG_MAP(CPhilosopherView)
ON_COMMAND(ID_PLAY_ONCE, OnPlayOnce)
ON_COMMAND(ID_PLAY_MANY, OnPlayMany)
ON_UPDATE_COMMAND_UI(ID_PLAY_MANY, OnUpdatePlayMany)
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPhilosopherView construction/destruction
CPhilosopherView::CPhilosopherView()
{
// TODO: add construction code here
for(int i = 0; i < PHIL_NUM; i++)
m_pThread[i] = NULL;
m_pMutex = new CMutex; //用于控制對數(shù)組chopSticks的訪問
m_pEvent = new CEvent(FALSE, TRUE); //用于控制線程,讓線程同時開始執(zhí)行,bManualReset 為true
}
CPhilosopherView::~CPhilosopherView()
{
delete m_pMutex;
delete m_pEvent;
}
BOOL CPhilosopherView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CPhilosopherView drawing
void CPhilosopherView::OnDraw(CDC* pDC)
{
CPhilosopherDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
int chopStartX[6], chopStartY[6], chopEndX[6], chopEndY[6];
int philX[6], philY[6];
int i;
CPen pen(PS_SOLID, 3, RGB(0, 0, 0));
CRect rect = CRect(150, 150, 150+DESK_DIAMETER, 150+DESK_DIAMETER);
//畫圓桌
pDC->Ellipse(rect);
CHOP_COORDINATE(150, 150);
CPen *pOldPen = (CPen*)pDC->SelectObject(&pen);
//畫筷子
for(i = 0; i < PHIL_NUM; i++)
{
pDC->MoveTo(chopStartX[i], chopStartY[i]);
pDC->LineTo(chopEndX[i], chopEndY[i]);
}
pDC->SelectObject(pOldPen);
PHIL_COORDINATE(150, 150);
//畫哲學家
for(i = 0; i< PHIL_NUM; i++)
{
pDC->Ellipse(philX[i], philY[i], philX[i] + PHIL_DIAMETER, philY[i] + PHIL_DIAMETER);
}
}
/////////////////////////////////////////////////////////////////////////////
// CPhilosopherView printing
BOOL CPhilosopherView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CPhilosopherView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CPhilosopherView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CPhilosopherView diagnostics
#ifdef _DEBUG
void CPhilosopherView::AssertValid() const
{
CView::AssertValid();
}
void CPhilosopherView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CPhilosopherDoc* CPhilosopherView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CPhilosopherDoc)));
return (CPhilosopherDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CPhilosopherView message handlers
void CPhilosopherView::OnPlayOnce()
{
// TODO: Add your command handler code here
int i, left, right;
int chopStartX[6], chopStartY[6], chopEndX[6], chopEndY[6];
int philX[6], philY[6];
PARAM *pParam = NULL;
for(i = 0; i < PHIL_NUM; i++)
{
chopSticks[i] = FALSE; //初始時筷子可用
}
m_pEvent->ResetEvent(); //初始時,m_pEvent不可訪問
CHOP_COORDINATE(150, 150); //生成筷子的坐標
PHIL_COORDINATE(150, 150); //生成哲學家的坐標
for(i = 0; i < PHIL_NUM; i++)
{ //生成要傳入線程的參數(shù)
pParam = new PARAM;
if(NULL == pParam)
{
break;
}
pParam->Id = i;
pParam->m_hWnd = this->m_hWnd;
pParam->philX = philX[i];
pParam->philY = philY[i];
left = i;
right = (i+1) % PHIL_NUM;
pParam->chopXY[0] = chopStartX[left];
pParam->chopXY[1] = chopStartY[left];
pParam->chopXY[2] = chopEndX[left];
pParam->chopXY[3] = chopEndY[left];
pParam->chopXY[4] = chopStartX[right];
pParam->chopXY[5] = chopStartY[right];
pParam->chopXY[6] = chopEndX[right];
pParam->chopXY[7] = chopEndY[right];
m_pThread[i] = AfxBeginThread(DineOnce, (LPVOID)pParam);
}
//Invalidate();
//Invalidate(FALSE);
m_pEvent->SetEvent();//是m_pEvent可訪問,激活所有的哲學家線程
pParam = NULL;
}
/**********************************************************************
DineOnce 線程函數(shù)一直處于Lock的調(diào)用,這是因為線程的啟動也要一段時間,若線程
執(zhí)行的時間小于線程創(chuàng)建的時間,則有可能先被創(chuàng)建的線程已經(jīng)執(zhí)行完畢,而
后面的線程還沒開始執(zhí)行。
***********************************************************************/
UINT DineOnce(LPVOID pParam)
{
m_pEvent->Lock(); //線程阻塞,直到全部的線程都被啟動,從而使所有的線程同時執(zhí)行
PARAM *m_pParam = (PARAM*)pParam;
int left, right;
BOOL canDine = FALSE;
CWnd wnd;
CDC *pDC;
CPen pen;
CBrush brush, *pOldBrush;
left = m_pParam->Id;
right = (m_pParam->Id + 1) % PHIL_NUM;
//檢查筷子是否可用,若可用則進餐
m_pMutex->Lock();
if(FALSE == chopSticks[left]
&& FALSE == chopSticks[right])
{
chopSticks[left] = chopSticks[right] = TRUE;
canDine = TRUE;
}
m_pMutex->Unlock();
wnd.Attach(m_pParam->m_hWnd);
pDC=wnd.GetDC();
//根據(jù)是否可就餐畫圖
if(TRUE == canDine)
{
brush.CreateSolidBrush(RGB(0, 255, 0));
pOldBrush=(CBrush*)pDC->SelectObject(&brush);
pDC->Ellipse(m_pParam->philX, m_pParam->philY,
m_pParam->philX + PHIL_DIAMETER, m_pParam->philY + PHIL_DIAMETER);
pen.CreatePen(PS_SOLID, 3, RGB(0, 255, 0));
pDC->SelectObject(&pen);
pDC->MoveTo(m_pParam->philX + PHIL_DIAMETER/2, m_pParam->philY + PHIL_DIAMETER/2);
pDC->LineTo(m_pParam->chopXY[2], m_pParam->chopXY[3]);
pDC->MoveTo(m_pParam->philX + PHIL_DIAMETER/2, m_pParam->philY + PHIL_DIAMETER/2);
pDC->LineTo(m_pParam->chopXY[6], m_pParam->chopXY[7]);
pDC->SelectObject(pOldBrush);
}
else
{
brush.CreateSolidBrush(RGB(255, 0, 0));
pOldBrush=(CBrush*)pDC->SelectObject(&brush);
pDC->Ellipse(m_pParam->philX, m_pParam->philY,
m_pParam->philX + PHIL_DIAMETER, m_pParam->philY + PHIL_DIAMETER);
pDC->SelectObject(pOldBrush);
}
wnd.Detach();
delete m_pParam;
return 0L;
}
void CPhilosopherView::OnPlayMany()
{
// TODO: Add your command handler code here
int i, left, right;
int chopStartX[6], chopStartY[6], chopEndX[6], chopEndY[6];
int philX[6], philY[6];
PARAM *pParam = NULL;
for(i = 0; i < PHIL_NUM; i++)
{
chopSticks[i] = FALSE;
}
//Finished數(shù)字的作用用來表示線程是否已經(jīng)執(zhí)行完成,用于控制“進行多次”菜單是否可以使用
for (i =0; i< PHIL_NUM; i++)
{
Finished[i] = FALSE; //初始時,F(xiàn)inished為false,若線程執(zhí)行完成,F(xiàn)inished為true
}
m_pEvent->ResetEvent();
CHOP_COORDINATE(150, 150);
PHIL_COORDINATE(150, 150);
for(i = 0; i < PHIL_NUM; i++)
{
pParam = new PARAM;
if(NULL == pParam)
{
break;
}
pParam->Id = i;
pParam->m_hWnd = this->m_hWnd;
pParam->philX = philX[i];
pParam->philY = philY[i];
left = i;
right = (i+1) % PHIL_NUM;
pParam->chopXY[0] = chopStartX[left];
pParam->chopXY[1] = chopStartY[left];
pParam->chopXY[2] = chopEndX[left];
pParam->chopXY[3] = chopEndY[left];
pParam->chopXY[4] = chopStartX[right];
pParam->chopXY[5] = chopStartY[right];
pParam->chopXY[6] = chopEndX[right];
pParam->chopXY[7] = chopEndY[right];
m_pThread[i] = AfxBeginThread(DineMany, (LPVOID)pParam);
}
Invalidate();
m_pEvent->SetEvent(); //同上的解釋
pParam = NULL;
}
/////////////////////////////////////////////////////////////////////////////
UINT DineMany(LPVOID pParam)
{
m_pEvent->Lock();
PARAM *m_pParam = (PARAM*)pParam;
int left, right;
int TimeDelay = TIME, SleepTime;
BOOL canDine = FALSE;
CWnd wnd;
CDC *pDC;
CPen pen1, pen2, *pOldPen;
CBrush brush1, brush2, *pOldBrush;
left = m_pParam->Id;
right = (m_pParam->Id + 1) % PHIL_NUM;
wnd.Attach(m_pParam->m_hWnd);
pDC=wnd.GetDC();
brush1.CreateSolidBrush(RGB(0, 255, 0));
brush2.CreateSolidBrush(RGB(255, 0, 0));
pen1.CreatePen(PS_SOLID, 3, RGB(0, 255, 0));
pen2.CreatePen(PS_SOLID, 3, RGB(255, 255, 255));
while(TimeDelay > 0)
{
m_pMutex->Lock();
if(FALSE == chopSticks[left]
&& FALSE == chopSticks[right])
{
chopSticks[left] = chopSticks[right] = TRUE;
canDine = TRUE;
}
m_pMutex->Unlock();
if(TRUE == canDine)
{
pOldBrush = (CBrush*)pDC->SelectObject(&brush1);
pDC->Ellipse(m_pParam->philX, m_pParam->philY,
m_pParam->philX+PHIL_DIAMETER, m_pParam->philY+PHIL_DIAMETER);
pDC->SelectObject(&pen1);
pDC->MoveTo(m_pParam->philX+PHIL_DIAMETER/2, m_pParam->philY + PHIL_DIAMETER/2);
pDC->LineTo(m_pParam->chopXY[2], m_pParam->chopXY[3]);
pDC->MoveTo(m_pParam->philX + PHIL_DIAMETER/2, m_pParam->philY + PHIL_DIAMETER/2);
pDC->LineTo(m_pParam->chopXY[6], m_pParam->chopXY[7]);
srand((unsigned)time(NULL));
SleepTime = ((rand() % 250 +250) - (rand() % 250 -250)) / 2;
Sleep(SleepTime);
TimeDelay -= SleepTime;
if(TimeDelay < 0 ) break;
//進餐后,防線筷子給其他哲學家使用
m_pMutex->Lock();
chopSticks[left] = chopSticks[right] = FALSE;
m_pMutex->Unlock();
//開始思考
canDine = FALSE;
}
if(FALSE == canDine)
{
pOldPen = (CPen*)pDC->SelectObject(&pen2);
pDC->MoveTo(m_pParam->philX + PHIL_DIAMETER/2, m_pParam->philY + PHIL_DIAMETER/2);
pDC->LineTo(m_pParam->chopXY[2], m_pParam->chopXY[3]);
pDC->MoveTo(m_pParam->philX + PHIL_DIAMETER/2, m_pParam->philY + PHIL_DIAMETER/2);
pDC->LineTo(m_pParam->chopXY[6], m_pParam->chopXY[7]);
pDC->SelectObject(&brush2);
pDC->Ellipse(m_pParam->philX, m_pParam->philY,
m_pParam->philX + PHIL_DIAMETER, m_pParam->philY + PHIL_DIAMETER);
pDC->SelectObject(pOldPen);
//思考一段時間
srand((unsigned)time(NULL));
SleepTime = ((rand() % 500 +500) - (rand() % 500 -500)) / 2;
Sleep(SleepTime);
//將持續(xù)時間減去思考時間
TimeDelay -= SleepTime;
}
}
wnd.Detach();
Finished[m_pParam->Id] = TRUE; //線程執(zhí)行完成
delete m_pParam;
return 0L;
}
void CPhilosopherView::OnUpdatePlayMany(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
int i;
BOOL flag = TRUE;
for (i =0; i < PHIL_NUM; i++)
{
//若還有線程沒有執(zhí)行完成,則菜單不可用
if (FALSE == Finished[i])
{
flag = FALSE;
break;
}
}
pCmdUI->Enable(flag);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -