操作系统 实验十
哲学家进餐问题
使用互斥量和事件进行同步和互斥控制
#include<windows.h>
#include<process.h>
#include<math.h>
#define DEGRESS_TO_RADIAN(x) (x)*3.14/180
#pragma comment(lib,"user32.lib")
#pragma comment(lib,"gdi32.lib")
typedef struct
{
HWND hWnd;
int chopXY[8];
int Id;
int isEating;
}PARAM;
#define PHIL_NUM 5
#define START_POINT 150
#define DESK_DIAMETER 200
#define PHIL_DIAMETER 30
#define CHOP_LENGHT 50
#define TIME 10000
int chopSticks[PHIL_NUM];
int Finished[PHIL_NUM];
HANDLE hMetex;
HANDLE hEvent;
unsigned int __stdcall DineMany(LPVOID pParam);
int WINAPI WinMain(HINSTANCE,HINSTANCE hPreInstance,LPSTR pszCamdLine,int nCmdShow);
LRESULT CALLBACK WindowProc(HWND hWnd,UINT uMshId,WPARAM wParam,LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPreInstance,LPSTR pszCmdLine,int nCmdShow)
{
static char szAppName[]="哲学家进餐";
HWND hWnd;
MSG msg;
WNDClASS wndClass;
wndClass.style=CS_VREDRAW|CS_HREDRAW;
wndClass.lpfnWndProc=WindowProc;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hInstance=hInstance;
wndClass.hIcon=LoadIcon(NULL,IDI_QUESTION);
wndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndClass.hbrBackground=(HANDLE)GetStockObject(WHITE_BRUSH);
wndClass.lpszMenuName=NULL;
wndClass.lpszClassName=szAppName;
if(0==RegisterClass(&wndClass))
return 0;
hWnd=CreateWindow(szAppName,szAppName,WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
CW_USEDEFAULT,NULL,NULL,hInstance,NULL);
if(0==hWnd) return 0;
ShowWindow(hWnd,nCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WindowProc(HWND hWnd,UINT uMsgId,WPARAM wParam,LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT paintStruct;
HANDLE hThread[PHIL_NUM];
int left,right;
static int chopStartX[PHIL_NUM],chopStartY[PHIL_NUM];
static int chopEndX[PHIL_NUM],chopEndY[PHIL_NUM];
static int philX[PHIL_NUM],philY[PHIL_NUM];
static PARAM pParam[PHIL_NUM];
HPEN hPenWhite,hOldPen;
int i;
switch(uMsgId)
{
case WM_CREATE:
hMutex=CreateMutex(NULL,FALSE,NULL);
hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
for(i=0;i<PHIL_NUM;i++)
{
chopStartX[i]=(int)((START_POINT)+DESK_DIAMETER/2+
DESK_DIAMETER/4*sin(DEGRESS_TO_RADIAN(90+
(360.0/PHIL_NUM)*i)));
chopStartY[i]=(int)((START_POINT)+DESK_DIAMETER/2+
DESK_DIAMETER/4*cos(DEGRESS_TO_RADIAN(90+
(360.0/PHIL_NUM)*i)));
chopEndX[i]=(int)((START_POINT)+DESK_DIAMETER/2+
DESK_DIAMETER/2*sin(DEGRESS_TO_RADIAN(90+
(360.0/PHIL_NUM)*i)));
chopEndY[i]=(int)((START_POINT)+DESK_DIAMETER/2+
DESK_DIAMETER/2*cos(DEGRESS_TO_RADIAN(90+
(360.0/PHIL_NUM)*i)));
philX[i]=(int)((START_POINT)*DESK_DIAMETER/2+
(DESK_DIAMETER/2+PHIL_DIAMETER)*cos(DEGRESS_TO_RADIAN(-(360.0/(PHIL_NUM*2))-(360.0/PHIL_NUM)*1))
-PHIL_DIAMETER/2);
philY[i]=(int)((START_POINT)*DESK_DIAMETER/2+
(DESK_DIAMETER/2+PHIL_DIAMETER)*cos(DEGRESS_TO_RADIAN(-(360.0/(PHIL_NUM*2))-(360.0/PHIL_NUM)*1))
-PHIL_DIAMETER/2);
chopSticks[i]=0;
Finished[i]=1;
}
break;
case WM_PAINT:
hDC=BeginPaint(hWnd,&paintStruct);
{
Ellipse(hDC,START_POINT,START_POINT,START_POINT+
DESK_DIAMETER,START_POINT+DESK_DIAMETER);
for(i=0;i<PHIL_NUM;i++)
{
MoveToEx(hDC,chopStartX[i],chopStartY[i],NULL);
LineTo(hDC,chopEndX[i],chopEndY[i]);
}
for(i=0;i<PHIL_NUM;i++)
Ellipse(hDC,philX[i],philY[i],philX[i]+PHIL_DIAMETER,
philY[i]+PHIL_DIAMETER);
for(i=0;i<PHIL_NUM;i++)
{
if(pParam[i].isEating==1)
{
MoveToEx(hDC,philX[i]+PHIL_DIAMETER/2,philY[i]+PHIL_DIAMETER/2,NULL);
LineTo(hDC,pParam[i].chopXY[2],pParam[i].chopXY[3]);
MoveToEx(hDC,philX[i]+PHIL_DIAMETER/2,
philY[i]+PHIL_DIAMETER/2,NULL);
LineTo(hDC,pParam[i].chopXY[6],pParam[i].chopXY[7]);
}
else
{
hPenWhite=CreatePen(PS_SOLID,3,RGB(255,255,255));
hOldPen=SelectObject(hDC,hPenWhite);
MoveToEx(hDC,philX[i]+PHIL_DIAMETER/2,
philY[i]+PHIL_DIAMETER/2,NULL);
LineTo(hDC,pParam[i].chopXY[2],pParam[i].chopXY[3]);
MoveToEx(hDC,philX[i]+PHIL_DIAMETER/2,
philY[i]+PHIL_DIAMETER/2,NULL);
LineTo(hDC,pParam[i].chopXY[6],pParam[i].chopXY[7]);
SelectObject(hDC,hOldPen);
DeleteObject(hPenWhite);
}
}
TextOut(hDC,20,20,"press s",7);
}
EndPaint(hWnd,&paintStruct);
break;
case WM_CHAR:
if(wParam=='s'||wParam=='S')
{
for(i=0;i<PHIL_NUM;i++)
chopSticks[i]=FALSE;
ResetEvent(hEvent);
for(i=0;i<PHIL_NUM;i++)
{
pParam[i].Id=i;
pParam[i].hWnd=hWnd;
left=i;
right=(i+1)%PHIL_NUM;
pParam[i].chopXY[0]=chopStartX[left];
pParam[i].chopXY[1]=chopStartY[left];
pParam[i].chopXY[2]=chopEndX[left];
pParam[i].chopXY[3]=chopEndY[left];
pParam[i].chopXY[4]=chopStartX[right];
pParam[i].chopXY[5]=chopStartY[right];
pParam[i].chopXY[6]=chopEndX[right];
pParam[i].chopXY[7]=chopEndY[right];
pParam[i].isEating=0;
hThread[i]=(HANDLE)_beginthreadex(NULL,0,
DineMany,&pParam[i],0,NULL);
}
InvalidateRect(hWnd,NULL,FALSE);
SetEvent(hEvent);
}
break;
case WM_CLOSE:
for(i=0;i<PHIL_NUM;i++)
CloseHandle(hThread[i]);
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd,uMsgId,wParam,lParam);
}
return 0;
}
unsigned int __stdcall DineMany(LPVOID pParam)
{
PARAM *m_pParam=(PARAM*)pParam;
int left,right;
int TimeDelay=TIME,SleepTime;
BOOL canDine=FALSE;
WaitForSingleObject(hEvent,INFINITE);
left=m_pParam->Id;
right=(m_pParam->Id+1)%PHIL_NUM;
while(TimeDelay>0)
{
WaitForSingleObject(hMutex,INFINITE);
if(FALSE==chopSticks[left]&&FALSE==chopSticks[right])
{
chopSticks[left]=TRUE;
chopSticks[right]=TRUE;
canDine=TRUE;
}
ReleaseMutex(hMutex);
if(TRUE==canDine)
{
m_pParam->isEating=1;
InvalidateRect(m_pParam->hWnd,NULL,FALSE);
srand((unsigned)time(NULL));
SleepTime=((rand()%250+250)-(rand()%250-250))/2;
Sleep(SleepTime);
TimeDelay=TimeDelay-SleepTime;
WaitForSingleObject(hMutex,INFINITE);
chopSticks[left]=FALSE;
chopSticks[right]=FALSE;
ReleaseMutex(hMutex);
canDine=FALSE;
m_pParam->isEating=0;
SetEvent(hEvent);
}
if(FALSE==canDine)
{
srand((unsigned)time(NULL));
SleepTime=(rand()%500+500)-(rand()%500-500))/2;
Sleep(SleepTime);
TimeDelay=TimeDelay-SleepTime;
}
}
Finished[m_pParam->Id]=TRUE;
return 0L;
}