#include <Windows.h>
#include <stdio.h>
#include <process.h>
#include <conio.h>
#include <time.h>

#define CHAIRS 3  //椅子的个数
#define BARBERS 1 //理发师的个数
#define CUSTOMESTOCOME 7 //将要来的顾客的数量

typedef HANDLE SEMAPHORE;

static int count = 0; //记录理发店顾客的总数,初始化位0
int leaved = 0;
int waiting = 0;
time_t endtime = 0;  //关闭营业时间

HANDLE  customers;
HANDLE  barbers;

HANDLE hMutex;

DWORD WINAPI barber(LPVOID lpParam);		//理发师线程函数
DWORD WINAPI customer(LPVOID lpParam);		//顾客线程函数

//理发师理发
void cutHair();

//顾客坐到椅子上等待
void getChair();

//等待顾客到来
void wait();

//顾客离开
void customerLeave();

//顾客进入
void customerEnter();

void up(HANDLE hHandle)
{
	ReleaseSemaphore(hHandle, 1, NULL);

	//ResumeThread(hHandle);
}

void upMutex(HANDLE hMutex)
{
	ReleaseMutex(hMutex);
}

void down(HANDLE hHandle)
{
	WaitForSingleObject(hHandle, INFINITE);
}

int main()
{
	int i = 0, j = 0;
	int nTime = 0;
	HANDLE hBarberThread;
	HANDLE hCustomerThread[CUSTOMESTOCOME] = {0};

	endtime = time(0);

	customers = CreateSemaphore(NULL, 0, CHAIRS, NULL);
	barbers = CreateSemaphore(NULL, 1, BARBERS, NULL);
	hMutex = CreateMutex(NULL, FALSE, L"mutex");

	
	hBarberThread = CreateThread(NULL, 0, barber, NULL, 0, NULL);

	while(count < CUSTOMESTOCOME)
	{
		hCustomerThread[i] = CreateThread(NULL, 0, customer, NULL, 0, NULL);
		i++;
		srand((unsigned int) (time(0)));
		nTime = rand() % 1000;
		Sleep(nTime);
	}

	//WaitForMultipleObjects(CUSTOMESTOCOME, hCustomerThread, TRUE, INFINITE);
	//WaitForSingleObject(hBarberThread, INFINITE);

	for(j = 0; j < CUSTOMESTOCOME; j++)
	{
		CloseHandle(hCustomerThread[j]);
	}

	CloseHandle(hBarberThread);

	CloseHandle(barbers);
	CloseHandle(customers);
	CloseHandle(hMutex);

	printf("离开顾客总数为: %d\n", leaved);
	system("pause");
	return 0;
}

DWORD WINAPI barber(LPVOID lpParam)		//理发师线程函数
{
	time_t currenttime = time(0);

	while(currenttime < endtime)
	{
		down(customers);

		down(hMutex);

		waiting = waiting - 1;

		upMutex(hMutex);

		cutHair();

		up(barbers);
		currenttime = time(0);
	}

	printf("打烊了。。。");
	return 0;
}

DWORD WINAPI customer(LPVOID lpParam)		//顾客线程函数
{
	customerEnter();

	down(hMutex);

	printf("等待的顾客数:%d\n", waiting);
	printf("空椅子数:%d\n", CHAIRS - waiting);

	if(waiting < CHAIRS)
	{
		if(waiting != 0)
		{
			wait();
		}

		waiting = waiting + 1;

		up(customers);
		upMutex(hMutex);

		down(barbers);

		getChair();
	}
	else
	{
		upMutex(hMutex);

		customerLeave();
	}
	return 0;
}

//理发师理发
void cutHair()
{
	static int served = 0;
	served++;
	printf("理发师帮第%d位被服务的顾客理发\n", served);
	Sleep(1000);
	printf("第%d位被服务的顾客理完发\n", served);
}

//顾客坐到椅子上等待
void getChair()
{
	Sleep(1050);
}

//等待顾客到来
void wait()
{
	printf("有空位,第%d位顾客就坐\n", count);
}

//顾客离开
void customerLeave()
{
	printf("没有空位,第%d位顾客离开\n", count);
	leaved++;
}

//顾客进入
void customerEnter()
{
	SYSTEMTIME sys;
	count++;
	
	GetLocalTime(&sys);
	printf("第%d位顾客进来\n", count);
}