#include<stdio.h>
#include<Windows.h>
#include<string.h>
#include<iostream>
CRITICAL_SECTION Only_One; //用于控制只有一个生产者在临界区
//定义缓冲区大小
#define MAX_BUFFER_NUM 3
//定义消费者个数
#define Cosumer_Size 1
 
 //定义最大线程数
#define MAX_THREAD_NUM 4
//定义信号量初始值和最大值
#define IInitialCount 1
#define IMaximumCount 1
//初始化缓冲区
 int Buffer_Critical[MAX_BUFFER_NUM]={0};
 HANDLE h_mutex;
 HANDLE empty_semephore;
 
 //记录每个用户进程的需要产品数
 int Cosumer_Thread_Num[Cosumer_Size]={0};
 
 //创建信号量数组
 HANDLE h_Semaphore[MAX_THREAD_NUM];
 
 //临界区对象数组
 CRITICAL_SECTION PC_Critical[MAX_BUFFER_NUM];
 
typedef struct ThreadInfo{
 //进程号
 int Thread_Num;
 
 //进程类型
 char Thread_Type;
 
 //进程启动时间
 int Thread_Time;
 
 //生产者进程号
 int Producer_Thread_Num[20];
}*Struct_Pointer;
//线程执行时用于输出的函数
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
 int q=(int)lpParam;
 printf("%d号进程等待empty_semephore信号量,检查是否存在空闲区\n",q);
 WaitForSingleObject(empty_semephore,INFINITE);
 {
  printf("%d号进程存在空闲区供写入\n",q);
  printf("%d号进程等待互斥量h_mutex,检查是否有另一生产者在写\n",q);
  WaitForSingleObject(h_mutex,INFINITE);
  {
   printf("%d号进程没有其他生产者在写入\n",q);
   EnterCriticalSection(&Only_One);
   printf("%d号进程进入临界区\n",q);
   printf("%d 号线程运行中!!\n",q);
   int i=0;
   for(i=0;i<MAX_BUFFER_NUM ;i++ )
   {
    if(Buffer_Critical[i]==0)
    {
     printf("%d 号线程分配缓冲区成功!!\n",q);
     break;
    }
   }
   LeaveCriticalSection(&Only_One);
   printf("%d 号线程退出临界区\n",q);
   Buffer_Critical[i]=q;
   printf("%d 号线程写入缓冲区成功!!\n",q);
   //=CreateSemaphore(NULL,IInitialCount,IMaximumCount,NULL);
   ReleaseSemaphore(h_Semaphore[q-1],1,NULL);
   printf("%d 号线程信号量写入成功!!\n",q);
  }
  ReleaseMutex(h_mutex);
  printf("%d 号线程互斥量释放成功\n",q);
 }
 ReleaseSemaphore(empty_semephore,1,NULL);
 printf("%d 号线程信号量释放成功\n",q);
}
//处理消费者线程函数
DWORD WINAPI ThreadProc_Cos(LPVOID lpParam)
{
 int Count_Signal=0;
 int num=((Struct_Pointer)lpParam)->Thread_Num;
 int checkp=((Struct_Pointer)lpParam)->Producer_Thread_Num[0];
 int p=((Struct_Pointer)lpParam)->Thread_Num;
 if(Cosumer_Thread_Num[p-MAX_BUFFER_NUM-1]==0)
 {
  printf("%d号线程没有消费请求,结束线程\n",p);
  return(0);
 }
 else
 {
  Count_Signal=Cosumer_Thread_Num[num-MAX_BUFFER_NUM-1];
  //使用循环获取等待的信号量数
  //for(int i=0; ; i++)
  //{
   //int temp_arry=((Struct_Pointer)lpParam)->Producer_Thread_Num[i];
   //if(temp_arry==0)
   //{
    //break;
   //}
   //else
   //{
    //Count_Signal+=1;
   //}
  //}
  
  //使用for循环等待所有进程完成
  printf("%d号线程等待消费完成\n",p);
  for(int i=0;i<Count_Signal;i++)
  {
   int temp_arry_Num=((Struct_Pointer)lpParam)->Producer_Thread_Num[i];
   
   WaitForSingleObject(h_Semaphore[temp_arry_Num-1],INFINITE);
   {
    //如果该进程已经完成则测试是否在缓冲区
    if(TryEnterCriticalSection(&PC_Critical[temp_arry_Num-1]))
    {
     printf("产品%d没有消费者在消费,可用!\n",temp_arry_Num);
    }
    else
    {
     printf("产品%d有消费者在消费,不可用!\n",temp_arry_Num);
    }
    EnterCriticalSection(&PC_Critical[temp_arry_Num-1]);
    printf("%d号进程进入产品%d临界区\n",p,temp_arry_Num);
    printf("%d号进程消费%d号产品\n",p,temp_arry_Num);
    LeaveCriticalSection(&PC_Critical[temp_arry_Num-1]);
    printf("%d号进程退出产品%d临界区\n",p,temp_arry_Num);
   }
  }
  printf("%d号消费者消费完毕,结束线程\n",p);
 }
}
void main()
{
 
 
 // 进程结构数组
 struct ThreadInfo Thread_Info[MAX_BUFFER_NUM+Cosumer_Size];
 
 //初始化排序数组
 int Sort_ThreadInfo[MAX_BUFFER_NUM+Cosumer_Size][2]={0} ;
 
 //
 //输入部分
 //
 
 //输入生产者线程
 for(int i=0;i<MAX_BUFFER_NUM;i++)
 {
  scanf("%d %c %d",&Thread_Info[i].Thread_Num,&Thread_Info[i].Thread_Type,&Thread_Info[i].Thread_Time);
  Sort_ThreadInfo[i][0]=Thread_Info[i].Thread_Num;
  Sort_ThreadInfo[i][1]=Thread_Info[i].Thread_Time;
 }
 
 //结束输入流
 //fflush(stdin);
 getchar();
 //输入消费者线程
 for(int i=0;i<Cosumer_Size;i++)
 {
  int Count_Producer_Num=0;
  char input[50];
  //初始化字符串
  memset(input,'\0',sizeof(input));
   //初始化数组
   memset(Thread_Info[i+Cosumer_Size].Producer_Thread_Num,0,sizeof(Thread_Info[i].Producer_Thread_Num));
  
  scanf("%[^\n]",&input);
  
  //结束输入流
  fflush(stdin);
  
  for(int j=0;j<sizeof(input);j++)
  {
   if(input[j]=='\n')
   {
    break;
   }
   if(j>4)
   {
    if(input[j]>='0'&&input[j]<='9')
    {
     Thread_Info[MAX_BUFFER_NUM+i].Producer_Thread_Num[Count_Producer_Num]=input[j]-'0';
     Count_Producer_Num+=1;
     Cosumer_Thread_Num[i]=Count_Producer_Num;
    }
   }
   else if(j==0)
   {
    Thread_Info[MAX_BUFFER_NUM+i].Thread_Num=input[j]-'0';
    Sort_ThreadInfo[MAX_BUFFER_NUM+i][0]=Thread_Info[MAX_BUFFER_NUM+i].Thread_Num;
   }
   else if(j==2)
   {
    Thread_Info[MAX_BUFFER_NUM+i].Thread_Type=input[j];
   }
   else if(j==4)
   {
    Thread_Info[MAX_BUFFER_NUM+i].Thread_Time=input[j]-'0';
    Sort_ThreadInfo[MAX_BUFFER_NUM+i][1]=Thread_Info[MAX_BUFFER_NUM+i].Thread_Time;
   }
  }
  
  
 }
 
 //对线程时间进行排序 0号为进程号,1为时间
 for(int i=0;i<MAX_BUFFER_NUM+Cosumer_Size;i++)
 {
  int Temp_sort=Sort_ThreadInfo[i][1];
  int Temp_sort_0=Sort_ThreadInfo[i][0];
  for(int j=i+1;j<MAX_BUFFER_NUM+Cosumer_Size;j++)
  {
   if(Temp_sort>=Sort_ThreadInfo[j][1])
   {
    Sort_ThreadInfo[i][0]=Sort_ThreadInfo[j][0];
    Sort_ThreadInfo[i][1]=Sort_ThreadInfo[j][1];
    Sort_ThreadInfo[j][0]=Temp_sort_0;
    Sort_ThreadInfo[j][1]=Temp_sort;
    Temp_sort_0=Sort_ThreadInfo[i][0];
    Temp_sort=Sort_ThreadInfo[i][1];
   }
  }
 }
 
 //
 //
 //
 
 //
 //初始化部分
 //
 //创建互斥量h_mutex
 h_mutex=CreateMutex(NULL,FALSE,NULL);
 
 //初始化产品是否已经生产的信号量数组
 for(int i=0;i<MAX_THREAD_NUM;i++)
 {
  h_Semaphore[i]=CreateSemaphore(NULL,0,1,NULL);
 }
 
 //空缓冲区数目信号量
 empty_semephore=CreateSemaphore(NULL,IInitialCount,IMaximumCount,NULL);
 
 //临界区对象数组
 for(int i=0;i<MAX_BUFFER_NUM;i++)
 {
 InitializeCriticalSection(&PC_Critical[i]);
 }
 //
 //
 //
 
 //
 //开始模拟
 //
 HANDLE Thread[MAX_BUFFER_NUM+Cosumer_Size];
 int Count_Num=0;
 //初始化临界区
 InitializeCriticalSection(&Only_One);
 while(1)
 {
  if(Thread_Info[(Sort_ThreadInfo[Count_Num][0])-1].Thread_Type=='p')
  {
   //为生产者创建进程 ,并传递进程号。
   Thread[Count_Num]=CreateThread(NULL,0,ThreadProc,(LPVOID)(Thread_Info[(Sort_ThreadInfo[Count_Num][0])-1].Thread_Num),0,NULL);
   Sleep(1);
   Count_Num+=1;
  }
  else if(Count_Num<MAX_BUFFER_NUM+Cosumer_Size)
  {
   
   Thread[Count_Num]=CreateThread(NULL,0,ThreadProc_Cos,(LPVOID)&(Thread_Info[(Sort_ThreadInfo[Count_Num][0])-1]),0,NULL);
   Sleep(1);
   Count_Num+=1;
  }
  if(Count_Num==MAX_BUFFER_NUM+Cosumer_Size)
  {
   break;
  }
 }
 Sleep(100000);
 printf("end");
}