vytah.cpp
上传用户:qzweiguo
上传日期:2022-07-31
资源大小:4k
文件大小:16k
源码类别:

其他小程序

开发平台:

C++ Builder

  1. /***************************************************************************
  2.  *   Copyright (C) 2007 by Jan Mares   *
  3.  *   maresj6@feld.cvut.cz   *
  4.  ***************************************************************************/
  5. #ifdef HAVE_CONFIG_H
  6. #include <config.h>
  7. #endif
  8. #include <iostream>
  9. #include <cstdlib>
  10. #include <ctime>
  11. #include <unistd.h>
  12. #include <sys/ipc.h>
  13. #include <sys/sem.h>
  14. #include <sys/types.h>
  15. #include <stdio.h>
  16. #include <math.h>
  17. #include <sys/shm.h>
  18. #include <sys/stat.h>
  19. #include <sys/mman.h>
  20. #include <semaphore.h>
  21. using namespace std;
  22. /* ################### */
  23. static unsigned int KAPACITA = 10;
  24. static unsigned int  ARGUMENTU = 5;
  25. key_t klic = 58742;
  26. int seg_id;
  27. int velikost;
  28.  int pocet_osob,pocet_pater,pocet_vytahu;
  29.  // explicitni posun o statove promene
  30.  #define KONEC -1
  31.  #define START 1
  32.  
  33.  #define P_STAV 0
  34.  // definice pro praci s vytahy
  35. #define V_POSUN 1
  36. #define V_PATRO 0
  37. #define V_SMER 1
  38. #define V_ODKUD 2
  39. #define V_KAM 3
  40. #define V_KAPACITA 4
  41. #define PRODLEVA 5
  42. #define NAHORU 1
  43. #define DOLU -1
  44. #define STOJI 0
  45. #define NENALEZEN -2
  46. sem_t * semaphores;
  47. /*###################*/
  48. struct shmid_ds shmbuffer; 
  49. /* Alokovani sdileneho pametoveno segmentu */ 
  50. int memory_allocate(int msize){
  51.     int segment_id, segment_size;
  52.     segment_size =  msize% getpagesize() + 1;
  53.     segment_id = shmget(IPC_PRIVATE, segment_size, IPC_CREAT | IPC_EXCL | 0777);
  54.     return segment_id;
  55. }
  56. void * memory_connect(int segment_id){
  57.     /* Pripojeni sdileneho segmentu */
  58.     return  shmat(segment_id, NULL, 0);
  59. }
  60. int memory_disconnect(int * memory){
  61.     shmdt(memory);
  62.     return 0;
  63. }
  64. int memory_dealloc(int segment_id){
  65.     shmctl(segment_id, IPC_RMID, NULL);
  66.     return 0;
  67.  }
  68.   /* Definovani unionu semun */ 
  69. union semun{
  70.     int val;
  71.     struct semid_ds *buf;
  72.     unsigned short int *array;
  73.     struct seminfo *__buf;
  74. };
  75.  /* Funkce ziska identifikator semaforu, nebo jej alokuje */
  76. int semaphore_allocation(key_t key,int semafor,  int sem_flags) {
  77.     return semget(key, semafor, sem_flags);
  78. }
  79.  /* Dealokace semaforu */
  80. int semaphore_deallocation(int semid, int semafor) {
  81.     union semun ignored_argument;
  82.     return semctl(semid, semafor, IPC_RMID, ignored_argument);
  83. }
  84. int semaphore_initialize(int semid,int semafor)
  85. {
  86.   union semun argument;
  87.   unsigned short values[1];
  88.   values[0] =0;
  89.   argument.array = values;
  90.   return semctl(semid, semafor, SETALL, argument);
  91. }
  92. /* Operace wait */
  93. int semaphore_wait(int semid,int semafor)
  94. {
  95.   //struct sembuf operations[1];
  96.   /* Pouzij prvni(jediny) semafor */
  97.   //operations[0].sem_num = semafor;
  98.   /* Zmensi o 1 */
  99.   //operations[0].sem_op = -1;
  100.   /* Nastaveni hodnoty SEM_NUDO */
  101.   //operations[0].sem_flg = SEM_UNDO;
  102.   //return semop(semid, operations, 1);
  103.   return sem_wait(&semaphores[semafor]);
  104. }
  105. /* Operace post */
  106. int semaphore_post(int semid, int semafor)
  107. {
  108. /*
  109.   struct sembuf operations[1];
  110.   operations[0].sem_num = semafor;
  111.   operations[0].sem_op = 1;
  112.   operations[0].sem_flg = SEM_UNDO;
  113.   return semop(semid, operations, 1);
  114. */
  115.     return sem_post(&semaphores[semafor]);
  116. }
  117. /*---------------------------*/
  118. int privolat(int id,key_t semafory,int pamet_id, int odkud, int kam){
  119.     int *pamet;
  120.     pamet = (int *)memory_connect(pamet_id);
  121.     int smer;
  122.     if(odkud>kam){
  123.         smer = DOLU;
  124.     } else {
  125.         smer = NAHORU;
  126.     }
  127.     
  128.     for(int i=0;i<pocet_vytahu;i++){
  129.         sem_wait(&semaphores[2*pocet_pater + i]); // blokujeme vytah
  130.         if(pamet[V_POSUN + (i*ARGUMENTU) + V_SMER] == smer){
  131.             switch(smer){
  132.                 case NAHORU :
  133.                     //cout<<"Jedouci nahoru"<<endl;
  134.                     if( (pamet[V_POSUN + (i*ARGUMENTU) + V_KAM] >= kam) && (pamet[V_POSUN + (i*ARGUMENTU) + V_PATRO]<= odkud)){
  135.                        // cout <<"a"<<endl;
  136.                         sem_post(&semaphores[2*pocet_pater + i]);
  137.                         memory_disconnect(pamet); // odpojeni od pameti
  138.                         return i;
  139.                     }
  140.                     if( (pamet[V_POSUN + (i*ARGUMENTU) + V_KAM] <= kam) && (pamet[V_POSUN + (i*ARGUMENTU) + V_PATRO] <= odkud)){
  141.                        // cout <<"b"<<endl;
  142.                         pamet[V_POSUN + (i*ARGUMENTU) + V_KAM] = kam;
  143.                         pamet[V_POSUN + (i*ARGUMENTU) + V_SMER] = smer;
  144.                         sem_post(&semaphores[2*pocet_pater + i]);
  145.                         memory_disconnect(pamet); // odpojeni od pameti
  146.                         return i;
  147.                     }
  148.                     break;
  149.                 case DOLU :
  150.                     //cout<<"Jedouci dolu"<<endl;
  151.                     if( (pamet[V_POSUN + (i*ARGUMENTU) + V_KAM] <= kam) && (pamet[V_POSUN + (i*ARGUMENTU) + V_PATRO] >= odkud)){
  152.                         //cout <<"c"<<endl;
  153.                         sem_post(&semaphores[2*pocet_pater + i]);
  154.                         memory_disconnect(pamet); // odpojeni od pameti
  155.                         return i;
  156.                     }
  157.                     if( (pamet[V_POSUN + (i*ARGUMENTU) + V_KAM] >= kam) && (pamet[V_POSUN + (i*ARGUMENTU) + V_PATRO] >= odkud)){
  158.                        // cout <<"d"<<endl;
  159.                         pamet[V_POSUN + (i*ARGUMENTU) + V_KAM] = kam;
  160.                         pamet[V_POSUN + (i*ARGUMENTU) + V_SMER] = smer;
  161.                         sem_post(&semaphores[2*pocet_pater + i]);
  162.                         memory_disconnect(pamet); // odpojeni od pameti
  163.                         return i;
  164.                     }
  165.                     break;
  166.             }
  167.         }
  168.         sem_post(&semaphores[2*pocet_pater + i]); // odblokujeme vytah
  169.     }
  170.     // nenalezen vytah jedouci v danem smeru -> mkrneme po vytahu, ktery stoji
  171.     for(int i=0;i<pocet_vytahu;i++){
  172.         sem_wait(&semaphores[2*pocet_pater + i]);
  173.         if(pamet[V_POSUN + (i*ARGUMENTU) + V_SMER] == STOJI){
  174.             //cout<<"Vybrano ze stojicich vytahu, ktere nastavime"<<endl;
  175.             cout<<"V "<<i<<" O "<<odkud<<" K "<<kam<<" S "<<smer<<endl;
  176.             pamet[V_POSUN + (i*ARGUMENTU) + V_ODKUD] = odkud;
  177.             pamet[V_POSUN + (i*ARGUMENTU) + V_KAM] = kam;
  178.             pamet[V_POSUN + (i*ARGUMENTU) + V_SMER] = smer;
  179.             pamet[V_POSUN + (i*ARGUMENTU) + V_PATRO] = odkud;
  180.             
  181.             semaphore_post(semafory,2*pocet_pater+i);
  182.           /*  
  183.             cout<<"vypis"<<endl;
  184.             for(int n=0;n<velikost;n++){
  185.                 cout<<pamet[n]<<" ";
  186.             }
  187.             cout<<endl;*/
  188.             
  189.             memory_disconnect(pamet);
  190.             
  191.             return i;
  192.         }
  193.         sem_post(&semaphores[2*pocet_pater + i]);
  194.     }
  195.     //cout <<"zel nic"<<endl;
  196.     memory_disconnect(pamet);
  197.     // nic nenalezeno -> oznamime to osobe, aby po urcite dobe zkusila zjistit zda je volny nejaky vytah
  198.     return NENALEZEN;
  199. }
  200. bool jsme_v_patre(int pamet_id,int vytah,int patro){
  201.     int *pamet;
  202.     pamet = (int *)memory_connect(pamet_id);
  203.     
  204.     int aktualni_patro;
  205.     aktualni_patro = pamet[V_POSUN + (vytah*ARGUMENTU) + V_PATRO];
  206.     
  207.     memory_disconnect(pamet);
  208.     
  209.     if(aktualni_patro == patro){
  210.         return true;
  211.     } else {
  212.         return false;
  213.     }
  214.     
  215. }
  216. void vytah(int vid,const key_t semafory,const int pamet_id){
  217.     int *pamet;
  218.     pamet = (int *)memory_connect(pamet_id);
  219.     int pozice,volno;
  220.     bool start;
  221.     int cislo;
  222.     pozice = V_POSUN + (vid-1)*ARGUMENTU;
  223.     
  224.     sem_wait(&semaphores[2*pocet_pater + vid]);
  225.     pamet[pozice + V_KAPACITA] = KAPACITA;
  226.     pamet[pozice + V_SMER] = STOJI;
  227.     pamet[pozice + V_PATRO] = 0;
  228.     pamet[pozice + V_KAM] = 0;
  229.     sem_post(&semaphores[2*pocet_pater + vid]);
  230.     
  231.     while( (pamet[P_STAV] != KONEC) && (pamet[pozice + V_SMER] == STOJI) ){ // cekame na prvotni impuls
  232.         sleep(PRODLEVA);
  233.     }
  234.     
  235.     start = true;
  236.     
  237.     while(pamet[P_STAV] != KONEC){
  238.                 
  239.         if( (start) && (pamet[pozice + V_PATRO] != pamet[pozice + V_ODKUD]) ){
  240.             pamet[pozice + V_PATRO] = pamet[pozice + V_ODKUD];
  241.             start = false;
  242.         }
  243.         
  244.         if(pamet[pozice + V_ODKUD] >pamet[pozice + V_KAM]){
  245.             pamet[pozice + V_SMER] = DOLU;
  246.         }
  247.         if(pamet[pozice + V_ODKUD] < pamet[pozice + V_KAM]){
  248.             pamet[pozice + V_SMER] = NAHORU;
  249.         }
  250.        // sem_wait(&semaphores[2*pocet_pater + vid]);
  251.         
  252.         
  253.         sem_wait(&semaphores[2*pocet_pater + vid]);
  254.         
  255.         if( pamet[pozice + V_PATRO] == pamet[pozice + V_KAM] ){
  256.            // cout<<"Jsem v konecne"<<endl;
  257.             pamet[pozice + V_SMER] = STOJI;
  258.             pamet[pozice + V_ODKUD] = pamet[pozice + V_KAM];
  259.             start = true;
  260.             cout<<"Vytah c."<<vid<<" stoji."<<endl;
  261.             if(pamet[pozice + V_KAPACITA]!= KAPACITA){
  262.                 cout<<"!!!!! vytah neni prazdny a stoji !!!!!"<<endl;
  263.             }
  264.         } else {
  265.             sleep(PRODLEVA%2); // nastup
  266.             
  267.             pamet[pozice + V_PATRO] = pamet[pozice + V_PATRO] +  pamet[pozice + V_SMER]; // presun
  268.         }
  269.         /* zajisteni "zaseku", aby vytah nevyjel mimo rozsah */
  270.         if( (pamet[pozice + V_PATRO] > pocet_pater)){
  271.             cout<<"Naraz o horni mantinel."<<endl;
  272.             pamet[pozice + V_SMER] = DOLU;
  273.             //pamet[pozice + V_PATRO] = pocet_pater;
  274.             //pamet[pozice + V_KAM] = pocet_pater;
  275.             //pamet[pozice + V_ODKUD] = pocet_pater;
  276.         }
  277.         if( (pamet[pozice + V_PATRO] < 0) ){
  278.             cout<<"Naraz na spodni mantinel."<<endl;
  279.             pamet[pozice + V_SMER] = NAHORU;
  280.             //pamet[pozice + V_PATRO] = 0;
  281.             //pamet[pozice + V_KAM] = 0;
  282.             //pamet[pozice + V_ODKUD] = 0;
  283.         }
  284.         /*-------*/
  285.         sem_post(&semaphores[2*pocet_pater + vid]);
  286.         
  287.         /* vypis info o vytahu */
  288.         cout << "Vytah c."<<vid<<endl;
  289.         cout<<"P D F T C"<<endl;
  290.         for(int n=pozice;n<(pozice+ARGUMENTU);n++){
  291.             cout<<pamet[n]<<" ";
  292.         }
  293.         cout<<endl;
  294.         /*----------*/
  295.         
  296.         sleep(PRODLEVA); // prejezd na dalsi patro
  297.     }
  298.     memory_disconnect(pamet);
  299. }
  300. void osoba(int oid,const key_t semafory, const int pamet_id){
  301.     int *pamet;
  302.     pamet = (int *)memory_connect(pamet_id);
  303.     
  304.     int min,max,odkud,kam,prace, vid,smer,pozice,cas;
  305.     bool nastup = false;
  306.     min = 0;
  307.     max = pocet_pater;
  308.     srand ( time(NULL) );
  309.     odkud = rand() % (max+1);
  310.     
  311.     while(pamet[P_STAV] != KONEC){
  312.         srand ( time(NULL) );
  313.         prace = rand()%(10+1);
  314.         sleep(prace);
  315.         do {
  316.              srand ( time(NULL) );
  317.             kam = rand() % (max+1);
  318.         } while (odkud == kam);
  319.         if(odkud>kam){
  320.             pozice = pocet_pater + kam;
  321.             smer = DOLU;
  322.         } else {
  323.             pozice = kam;
  324.             smer = NAHORU;
  325.         }
  326.         
  327.         //printf("Osoba %d pojede z %d. do %d.patra.n",oid,odkud,kam);
  328.         // cesta je vygenerovana
  329.         
  330.         nastup = false; // uvodni nastaveni
  331.         do {
  332.         
  333.              if(pamet[P_STAV]==KONEC){ // ukonceni cyklu
  334.                     memory_disconnect(pamet);
  335.                     return;
  336.             }
  337.                 
  338.             vid =  privolat(oid,semafory,pamet_id,odkud,kam);
  339.             while(vid == NENALEZEN){
  340.             
  341.                 if(pamet[P_STAV]==KONEC){
  342.                     memory_disconnect(pamet);
  343.                     return;
  344.                 }
  345.                 
  346.                 sleep(PRODLEVA%2);
  347.                 vid = privolat(oid,semafory,pamet_id,odkud,kam);
  348.             }
  349.            // cout<<"Osoba "<< oid << " pojede vytahem c."<<(vid)<<endl;
  350.             
  351.             while( pamet[V_POSUN + (vid*ARGUMENTU) + V_PATRO] != odkud ){
  352.                 if(pamet[P_STAV]==KONEC){
  353.                     memory_disconnect(pamet);
  354.                     return;
  355.                 }
  356.                 
  357.                 sleep(PRODLEVA%3 );
  358.             }
  359.             
  360.             //cout<<"Nastupuji do vytahu c."<<(vid)<<endl;
  361.             sem_wait(&semaphores[2*pocet_pater + vid]); // vyhradny pristup pro zmenu kapacity
  362.             pozice = V_POSUN + (vid*ARGUMENTU);
  363.             if ( (pamet[pozice + V_KAPACITA] > 0)  && (pamet[pozice + V_PATRO]==odkud) && (pamet[pozice + V_SMER] == smer) ){
  364.                 pamet[pozice + V_KAPACITA]--;
  365.                 if(smer == NAHORU){
  366.                     if(pamet[pozice + V_KAM] < kam){
  367.                         pamet[pozice + V_KAM] = kam;
  368.                     }
  369.                 } else if(smer == DOLU) {
  370.                     if(pamet[pozice + V_KAM]> kam){
  371.                         pamet[pozice + V_KAM] = kam;
  372.                     }
  373.                 }
  374.                 nastup = true;
  375.             } else {
  376.                 nastup = false;
  377.                 sem_post(&semaphores[2*pocet_pater + vid]); // vyhradny pristup pro zmenu kapacity
  378.             }
  379.         } while(nastup == false);
  380.         
  381.         // "nastoupili jsme do vytahu"
  382.         printf("Osoba %d nastoupila do vytahu %d na patre %d. (%d->%d)n",oid,vid+1, odkud,odkud,kam);
  383.         
  384.         sem_post(&semaphores[2*pocet_pater + vid]); // vyhradny pristup pro zmenu kapacity
  385.         while( (pamet[V_POSUN + (vid*ARGUMENTU) + V_PATRO]!=kam)  ){
  386.              
  387.              if(pamet[P_STAV]==KONEC){// ukonceni cyklu
  388.                     memory_disconnect(pamet);
  389.                     return;
  390.             }
  391.             
  392.             sleep(PRODLEVA%4);
  393.         }
  394.         // jsme v pozadovanem patre
  395.         sem_wait(&semaphores[2*pocet_pater + vid]); // vyhradny pristup pro zmenu kapacity
  396.         
  397.         pamet[V_POSUN + (vid*ARGUMENTU) + V_KAPACITA]++;
  398.         
  399.         printf("Osoba %d vystoupila z vytahu %d na patre %d. (%d->%d)n",oid,vid+1,kam,odkud,kam);
  400.         
  401.         sem_post(&semaphores[2*pocet_pater + vid]); // vyhradny pristup pro zmenu kapacity
  402.         odkud = kam;
  403.     }
  404.     memory_disconnect(pamet);
  405. }
  406. /*---------------------------*/
  407. int main(int argc, char *argv[]) {
  408.     //cout<<argc<<endl;
  409.     int pid;
  410.     srand ( time(NULL) );
  411.     
  412.     switch(argc) {
  413.     case 3 :
  414.         cout<<"zavolano s 3 parametry"<<endl;
  415.         pocet_osob = atoi(argv[1]);
  416.         pocet_pater = atoi(argv[2]);
  417.         pocet_vytahu = 2;
  418.         if( (pocet_osob < 0) || (pocet_pater < 0) ){
  419.             cout << "Se zapornymi cisly nelze pracovat" << endl;
  420.             return 1;
  421.         }
  422.         
  423.         break;
  424.     case 4 :
  425.        // cout<<"zavolano s 4 parametry"<<endl;
  426.         pocet_osob = atoi(argv[1]);
  427.         pocet_pater = atoi(argv[2]);
  428.         pocet_vytahu = atoi(argv[3]);
  429.         
  430.         if( (pocet_osob < 0) || (pocet_pater < 0) || (pocet_vytahu<=0)){
  431.             cout << "Se zapornymi cisly nelze pracovat" << endl;
  432.            return 0;
  433.         }
  434.         break;
  435.     default :
  436.         cout << "Ukazka volani : ./vytahy POCET_OSOB POCET_PATER POCET_VYTAHU=2" << endl;
  437.        return 0;
  438.     };
  439.     // vytvoreni  sdilene pameti
  440.     seg_id = memory_allocate((pocet_vytahu*ARGUMENTU+1)*sizeof(int));
  441.     int *pamet;
  442.     
  443.     pamet = (int *) memory_connect(seg_id);
  444.     pamet[0] = START;
  445.     memory_disconnect(pamet);
  446.     
  447.     // vytvoreni semaforu
  448.     velikost = 2*pocet_pater + pocet_vytahu + ARGUMENTU;
  449.     int semafory_patra;
  450.     semafory_patra = 2*pocet_pater;
  451.     
  452.     /*semaphore_allocation( klic,velikost,0777);
  453.     for(int i=0;i<velikost;i++){
  454.          semaphore_initialize(klic,i);
  455.     }*/
  456.     semaphores = new sem_t[velikost];
  457.     
  458.     
  459.     for(int z=0;z<semafory_patra;z++){
  460.         sem_init(&semaphores[z],1,0);
  461.     }
  462.     for(int m=semafory_patra;m<(velikost);m++){
  463.         sem_init(&semaphores[m],1,1);
  464.     }
  465.     //vytvoreni procesu pro vytahy
  466.     for(int j=0;j<pocet_vytahu;j++){
  467.         pid = fork();
  468.         if(pid == 0){
  469.             // vzniknul podrizeny proces
  470.             //cout<<"Vytvoren podrizeny proces - vytah"<<endl;
  471.             vytah(j+1,klic,seg_id);
  472.             return 0;
  473.         }
  474.     }
  475.     
  476.     // vytvoreni procesu pro osoby
  477.     for(int k=0;k<pocet_osob;k++){
  478.         pid = fork();
  479.         sleep(3);//zpozdeni vytvareni osob
  480.         if(pid == 0){
  481.             // vzniknul podrizeny proces
  482.            // cout<<"Vytvoreny podrizeny proces - osoba"<<endl;
  483.             osoba(k,klic,seg_id);
  484.             return 0;
  485.         }
  486.     }
  487.     
  488.     cin.get();
  489.     cin.get();
  490.     
  491.     // zruseni sdilene pameti
  492.     //int *pamet;
  493.     pamet = (int *) memory_connect(seg_id);
  494.     
  495.     for(int n=0;n<velikost;n++){
  496.         cout<<pamet[n]<<" ";
  497.     }
  498.     cout<<endl;
  499.     pamet[0] = KONEC;
  500.     memory_disconnect(pamet);
  501.     cout<<"Vypinam procesy..."<<endl;
  502.     sleep(10);
  503.     
  504.     memory_dealloc(seg_id);
  505.     
  506.     // zruseni semaforu
  507.     /*
  508.     for(int l=0;l<velikost;l++){
  509.         semaphore_deallocation(klic,l);
  510.     }
  511.     */
  512.         for(int i=0;i<velikost;i++){
  513.         sem_destroy(&semaphores[i]);
  514.         }
  515.         delete [] semaphores;
  516.     
  517.     return EXIT_SUCCESS;
  518. }