Листинг процедур, обеспечивающих решение задачи
Программа состоит из двух частей – клиента и сервера. Каждая программа клиент соответствует одному философу и посылает сообщения на сервер, который представляет собой стол, за которым сидят философы. Ниже представлены листинги процедур программ клиента и сервера.
Листинг программы-клиента.
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
LPTSTR myPipe = "\\\\.\\pipe\\mynamedpipe";
HANDLE hPipe;
int Number;
const char msg[6][50] = {"left the dinning room", "finished to eat", "is eating now", "wants to eat", "is thinking", "came to the table"};
void SendMsg(int message_num)
{
DWORD cbWritten;
int Buffer[2] = {Number, message_num};
WriteFile(hPipe, &Buffer, sizeof(Buffer), &cbWritten, NULL);
}
void start()
{
Form1->Memo1->Clear();
int N = atoi(ParamStr(1).c_str()); // количество философов
Number = atoi(ParamStr(2).c_str()); // номер данного философа
Form1->Caption="Philosopher "+IntToStr(Number);
while (1)
{
hPipe = CreateFile (myPipe,
GENERIC_READ |
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hPipe != INVALID_HANDLE_VALUE) break;
}
for(;;)
{
Form1->Memo1->Lines->Add("Philosopher "+ IntToStr(Number)+" "+msg[5]);
SendMsg(5); // философ подходит к столу
Sleep(random(2001)+3000);
HANDLE myMutex,myCritical;
// номер левого (правого) соседа философа
int LeftNeighbour=(Number + N -1)%N,
RightNeighbour=(Number+1)%N;
AnsiString LeftFork=IntToStr(LeftNeighbour),
RightFork=IntToStr(RightNeighbour),
eat=IntToStr(Number),
Crit="myCritical";
// создаётся мьютекс взаимного исключения входа в критическую оласть
myCritical = CreateMutex(NULL, false, Crit.c_str());
Form1->Memo1->Lines->Add("Philosopher "+ IntToStr(Number)+" "+msg[4]);
SendMsg(4); // философ размышляет
Sleep(random(2001)+3000);
Form1->Memo1->Lines->Add("Philosopher "+ IntToStr(Number)+" "+msg[3]);
SendMsg(3); // философ хочет есть
bool flag=false;
while (!flag)
{
// ожидание входа в критическую область
WaitForSingleObject(myCritical, INFINITE);
HANDLE LeftForkUsed,RightForkUsed;
// проверка состояния левого и правого соседей
LeftForkUsed = OpenMutex(MUTEX_ALL_ACCESS, 0, LeftFork.c_str());
RightForkUsed = OpenMutex(MUTEX_ALL_ACCESS, 0, RightFork.c_str());
if (!LeftForkUsed&&!RightForkUsed) // если соседи не едят
{
flag=true;
myMutex = CreateMutex(NULL, false, eat.c_str());
SendMsg(2); // философ приступает к приёму пищи
Form1->Memo1->Lines->Add("Philosopher "+ IntToStr(Number)+" "+msg[2]);
ReleaseMutex(myCritical); // выход из критической области
}
else
{
ReleaseMutex(myCritical);
CloseHandle(LeftForkUsed);
CloseHandle(RightForkUsed);
}
}
Sleep(random(2001)+3000);
SendMsg(1); // прекращение приёма пищи
Form1->Memo1->Lines->Add("Philosopher "+ IntToStr(Number)+" "+msg[1]);
Form1->Memo1->Lines->Add("Philosopher "+ IntToStr(Number)+" "+msg[0]);
SendMsg(0); //философ покидает столовую
CloseHandle(myMutex);
Sleep(random(2001)+3000);
}
}
void __fastcall TForm1::FormShow(TObject *Sender)
{
CreateThread(0, 0, (LPTHREAD_START_ROUTINE) start,0, 0, 0);
}
Листинг программы-сервера.
#include <vcl.h>
#include <stdio.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
LPTSTR myPipe = "\\\\.\\pipe\\mynamedpipe";
int Count = 5;
int bSize = 255, MaxWaitTime = 0;
const char msg[6][50] = {"left the dinning room", "finished to eat", "is eating now", "wants to eat", "is thinking", "came to the table"};
VOID InstanceThread(LPVOID lpvParam)
{
DWORD cbBytesRead;
BOOL ReadSuc;
HANDLE hPipe = (HANDLE) lpvParam;
int Buffer[2];
while (1)
{
//Считывание запросов клиента из канала
ReadSuc = ReadFile(
hPipe, // дескриптор канала
Buffer, // выходной буфер
sizeof(Buffer), // размер буфера
&cbBytesRead, // сколько байт считывать
NULL); // синхронный ввод/вывод
Form1->Memo1->Lines->Add("Philosopher "+ IntToStr(Buffer[0])+" "+msg[Buffer[1]]);
if (! ReadSuc || cbBytesRead == 0)
break;
}
FlushFileBuffers(hPipe);//сброс содержимого канала
DisconnectNamedPipe(hPipe);//разъединение
CloseHandle(hPipe);//закрытие дескриптора канала
}
void start()
{ Form1->Memo1->Clear();
char PARAMS[100];
for (int i = 0; i < Count; ++i)
{
sprintf(PARAMS, "%d %d", Count, i + 1);
ShellExecute(0, NULL, "Client.exe", PARAMS, NULL, SW_SHOW);
}
DWORD Identifier;
HANDLE hThread, hPipe;
BOOL ConnectSuc;
while (1)
{
hPipe = CreateNamedPipe(
myPipe, // имя канала
PIPE_ACCESS_DUPLEX, // доступ на
//чтение/запись
PIPE_TYPE_MESSAGE | // канал передачи
// сообщений
PIPE_READMODE_MESSAGE | // режим чтения
// сообщений
PIPE_WAIT, // блокирующийся режим
PIPE_UNLIMITED_INSTANCES, // максимальное число
// экземпляров этого канала в системе
bSize, // размер выходного буфера
bSize, // размер входного буфера
MaxWaitTime, // таймаут для клиента
NULL); // атрибуты
//безопасности отсутствуют
ConnectSuc = ConnectNamedPipe(hPipe, NULL) ?
TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
if (ConnectSuc)
{
hThread = CreateThread(
NULL, // Отсутствие атрибутов безопасности
0, // размер стека потока выбрать по умолчанию
(LPTHREAD_START_ROUTINE) InstanceThread,
(LPVOID) hPipe, // параметр потока
0, // не приостановленный
&Identifier); // возврат идентификатора потока
CloseHandle(hThread);
}
else
CloseHandle(hPipe);
}
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
CreateThread(0, 0, (LPTHREAD_START_ROUTINE) start,0, 0, 0);
}
Результат работы программы представлен на рисунке 2.
Рисунок 2 – Результат работы программы
Вывод
Таким образом, была решена задача об обедающих философах. Представленная программа предотвращает тупиковую ситуацию, когда ни один из философов не может начать есть, и обеспечивает корректное поведение философов. Программа была составлена средствами Borland Developer Studio 2006 Turbo C++.
Поиск по сайту: