//メール分配シミュレーション #include "stdafx.h" #include "string.h" #include "conio.h" #include "process.h" #include "windows.h" #define MAXQUE 20 typedef struct{//循環サイクルによる待ち行列 Start=Endのとき空 int Start,End; char data[MAXQUE][256]; } QueData; QueData Que[3]={{0,0,0},{0,0,0},{0,0,0}};int numP=4, Signal=true; int multex=1,multex2=1;//multex:送信者と郵便受け用, multex2:郵便受けと受信者用 int emptyQue(QueData *Que){//待ち行列が空のときtrue,それ以外のときfalse if((*Que).Start==(*Que).End) return true; return false; } int fullQue(QueData *Que){//待ち行列がフルのときtrue,それ以外のときfalse int next=(*Que).End+1;if(next>=MAXQUE) next=0; if((*Que).Start==next) return true; return false; } int enQue(QueData *Que,char V[]){//待ち行列にメッセージを入れる if(fullQue(Que))return true; strcpy((*Que).data[(*Que).End],V); (*Que).End++; if((*Que).End>=MAXQUE) (*Que).End=0; return false; } int deQue(QueData *Que, char str[]){//待ち行列からメッセージを受け取る if(emptyQue(Que)) return true; strcpy(str, (*Que).data[(*Que).Start]); (*Que).Start++; if((*Que).Start>=MAXQUE)(*Que).Start=0; return false; } void waitFull(QueData *Que){while(fullQue(Que)&& Signal )Sleep(10L);} //待ち行列がフルの間待つ void waitEmpty(QueData *Que){while(emptyQue(Que)&& Signal)Sleep(10L);}//待ち行列が空の間待つ void P(int *S){while((*S<=0)&& Signal);(*S)--;}//待ち行列セマフォP操作 void V(int *S){(*S)++;} //待ち行列セマフォV操作 void Sender(void *a){ char str[13][256]= //送信メッセージ { "A For want of nail, the shoe was lost,", "B Peter Piper picked a peck of pickled pepper.", "A For want of shoe, the horse was lost,", "A For want of horse, the rider was lost,", "B A peck of pickled pepper Peter Piper picked.", "A For want of rider, the battle was lost,", "A For want of battle, the kingdom was lost,", "B If Peter Piper picked a peck of pickled pepper,", "A And all from the want of a horseshoe nail!", "B $$END$$", //B宛 メッセージの終り "A $$END$$", //A宛 メッセージの終り "$$END$$"}; //郵便受け宛 メッセージの終り int L=0; while(1){//送信者はメールボックスがフルでなくなってから送信する waitFull(&Que[0]);P(&multex); if(!Signal){numP--;return;} if(enQue(&Que[0], str[L]))printf("\n Sender ** can't enQue for full Que"); else printf("\n Sender [%s] %d 番目",str[L],L); V(&multex); L++; if(L>=12){numP--; return;} Sleep(2L); if(getch()==26){Signal=false;numP--;return;}//[ctrl]Zで終了 } } void MailBox(void *a){ char str[256]; while(1){//郵便受けは待ち行列が空でなくなってから受信する。 waitEmpty(&Que[0]);P(&multex); if(!Signal){numP--;return;} if(deQue(&Que[0],str)) printf("\n Mail Box ** can't deQue for empty Que"); else printf("\n Mail Box[%s]",str); if(str[0]=='A'||str[0]=='B'){ int QS=str[0], QN = QS-'A'+1; waitFull(&Que[QN]);P(&multex2);//受信者がフルでなくなってから送信 if(enQue(&Que[QN], str))printf("\n proc %c ** can't enQue for full Que",QS); else printf("\n to proc %c [%s]",QS, str); V(&multex2); } V(&multex); if(strcmp(str,"$$END$$")==0){numP--;return;} Sleep(2L); if(getch()==26){Signal=false;numP--;return;}//[ctrl]Zで終了 } } void getMess(void *a){//受信者は自分宛メッセージが空でなくなってから受信する。 char strBuf[20][256], str[256], endStr[]="A $$END$$"; int NB=0, QN=(int)a, endFlag=false;char NC='A'+QN-1; if(QN==2)endStr[0]='B'; printf("\n start receiver %c",NC); while(1){ waitEmpty(&Que[QN]);P(&multex2); if(!Signal){numP--;return;}//[ctrl]Zで終了 if(deQue(&Que[QN],strBuf[NB])) printf("\n get %c ** can't deQue for empty Que",NC); else{ printf("\n get %c [%s]",NC,strBuf[NB]); if(strcmp(strBuf[NB],endStr)==0){ printf("\n get %c Process",NC); for(int i=0;i<=NB;i++)printf("\n [%s]",strBuf[i]); endFlag=true; } NB++; } V(&multex); if(endFlag){numP--;return;} Sleep(2L); if(getch()==26){Signal=false;numP--;return;}//[ctrl]Zで終了 } } int _tmain(int argc, _TCHAR* argv[]) { int S = 3, M = 4,A=1, B=2;//送信者,郵便受け,受信者スレッド起動 HANDLE H1=(HANDLE) _beginthread(Sender ,0,(void *)S); HANDLE H2=(HANDLE) _beginthread(MailBox,0,(void *)M); HANDLE H3=(HANDLE) _beginthread(getMess,0,(void *)A);//受信者は引数で識別 HANDLE H4=(HANDLE) _beginthread(getMess,0,(void *)B); while(numP!=0)Sleep(2L);printf("\n ***End");//子スレッドが終わったら終了 getch(); return 0; }