vytah.cpp
资源名称:vytah.cpp.zip [点击查看]
上传用户:qzweiguo
上传日期:2022-07-31
资源大小:4k
文件大小:16k
源码类别:
其他小程序
开发平台:
C++ Builder
- /***************************************************************************
- * Copyright (C) 2007 by Jan Mares *
- * maresj6@feld.cvut.cz *
- ***************************************************************************/
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include <iostream>
- #include <cstdlib>
- #include <ctime>
- #include <unistd.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- #include <sys/types.h>
- #include <stdio.h>
- #include <math.h>
- #include <sys/shm.h>
- #include <sys/stat.h>
- #include <sys/mman.h>
- #include <semaphore.h>
- using namespace std;
- /* ################### */
- static unsigned int KAPACITA = 10;
- static unsigned int ARGUMENTU = 5;
- key_t klic = 58742;
- int seg_id;
- int velikost;
- int pocet_osob,pocet_pater,pocet_vytahu;
- // explicitni posun o statove promene
- #define KONEC -1
- #define START 1
- #define P_STAV 0
- // definice pro praci s vytahy
- #define V_POSUN 1
- #define V_PATRO 0
- #define V_SMER 1
- #define V_ODKUD 2
- #define V_KAM 3
- #define V_KAPACITA 4
- #define PRODLEVA 5
- #define NAHORU 1
- #define DOLU -1
- #define STOJI 0
- #define NENALEZEN -2
- sem_t * semaphores;
- /*###################*/
- struct shmid_ds shmbuffer;
- /* Alokovani sdileneho pametoveno segmentu */
- int memory_allocate(int msize){
- int segment_id, segment_size;
- segment_size = msize% getpagesize() + 1;
- segment_id = shmget(IPC_PRIVATE, segment_size, IPC_CREAT | IPC_EXCL | 0777);
- return segment_id;
- }
- void * memory_connect(int segment_id){
- /* Pripojeni sdileneho segmentu */
- return shmat(segment_id, NULL, 0);
- }
- int memory_disconnect(int * memory){
- shmdt(memory);
- return 0;
- }
- int memory_dealloc(int segment_id){
- shmctl(segment_id, IPC_RMID, NULL);
- return 0;
- }
- /* Definovani unionu semun */
- union semun{
- int val;
- struct semid_ds *buf;
- unsigned short int *array;
- struct seminfo *__buf;
- };
- /* Funkce ziska identifikator semaforu, nebo jej alokuje */
- int semaphore_allocation(key_t key,int semafor, int sem_flags) {
- return semget(key, semafor, sem_flags);
- }
- /* Dealokace semaforu */
- int semaphore_deallocation(int semid, int semafor) {
- union semun ignored_argument;
- return semctl(semid, semafor, IPC_RMID, ignored_argument);
- }
- int semaphore_initialize(int semid,int semafor)
- {
- union semun argument;
- unsigned short values[1];
- values[0] =0;
- argument.array = values;
- return semctl(semid, semafor, SETALL, argument);
- }
- /* Operace wait */
- int semaphore_wait(int semid,int semafor)
- {
- //struct sembuf operations[1];
- /* Pouzij prvni(jediny) semafor */
- //operations[0].sem_num = semafor;
- /* Zmensi o 1 */
- //operations[0].sem_op = -1;
- /* Nastaveni hodnoty SEM_NUDO */
- //operations[0].sem_flg = SEM_UNDO;
- //return semop(semid, operations, 1);
- return sem_wait(&semaphores[semafor]);
- }
- /* Operace post */
- int semaphore_post(int semid, int semafor)
- {
- /*
- struct sembuf operations[1];
- operations[0].sem_num = semafor;
- operations[0].sem_op = 1;
- operations[0].sem_flg = SEM_UNDO;
- return semop(semid, operations, 1);
- */
- return sem_post(&semaphores[semafor]);
- }
- /*---------------------------*/
- int privolat(int id,key_t semafory,int pamet_id, int odkud, int kam){
- int *pamet;
- pamet = (int *)memory_connect(pamet_id);
- int smer;
- if(odkud>kam){
- smer = DOLU;
- } else {
- smer = NAHORU;
- }
- for(int i=0;i<pocet_vytahu;i++){
- sem_wait(&semaphores[2*pocet_pater + i]); // blokujeme vytah
- if(pamet[V_POSUN + (i*ARGUMENTU) + V_SMER] == smer){
- switch(smer){
- case NAHORU :
- //cout<<"Jedouci nahoru"<<endl;
- if( (pamet[V_POSUN + (i*ARGUMENTU) + V_KAM] >= kam) && (pamet[V_POSUN + (i*ARGUMENTU) + V_PATRO]<= odkud)){
- // cout <<"a"<<endl;
- sem_post(&semaphores[2*pocet_pater + i]);
- memory_disconnect(pamet); // odpojeni od pameti
- return i;
- }
- if( (pamet[V_POSUN + (i*ARGUMENTU) + V_KAM] <= kam) && (pamet[V_POSUN + (i*ARGUMENTU) + V_PATRO] <= odkud)){
- // cout <<"b"<<endl;
- pamet[V_POSUN + (i*ARGUMENTU) + V_KAM] = kam;
- pamet[V_POSUN + (i*ARGUMENTU) + V_SMER] = smer;
- sem_post(&semaphores[2*pocet_pater + i]);
- memory_disconnect(pamet); // odpojeni od pameti
- return i;
- }
- break;
- case DOLU :
- //cout<<"Jedouci dolu"<<endl;
- if( (pamet[V_POSUN + (i*ARGUMENTU) + V_KAM] <= kam) && (pamet[V_POSUN + (i*ARGUMENTU) + V_PATRO] >= odkud)){
- //cout <<"c"<<endl;
- sem_post(&semaphores[2*pocet_pater + i]);
- memory_disconnect(pamet); // odpojeni od pameti
- return i;
- }
- if( (pamet[V_POSUN + (i*ARGUMENTU) + V_KAM] >= kam) && (pamet[V_POSUN + (i*ARGUMENTU) + V_PATRO] >= odkud)){
- // cout <<"d"<<endl;
- pamet[V_POSUN + (i*ARGUMENTU) + V_KAM] = kam;
- pamet[V_POSUN + (i*ARGUMENTU) + V_SMER] = smer;
- sem_post(&semaphores[2*pocet_pater + i]);
- memory_disconnect(pamet); // odpojeni od pameti
- return i;
- }
- break;
- }
- }
- sem_post(&semaphores[2*pocet_pater + i]); // odblokujeme vytah
- }
- // nenalezen vytah jedouci v danem smeru -> mkrneme po vytahu, ktery stoji
- for(int i=0;i<pocet_vytahu;i++){
- sem_wait(&semaphores[2*pocet_pater + i]);
- if(pamet[V_POSUN + (i*ARGUMENTU) + V_SMER] == STOJI){
- //cout<<"Vybrano ze stojicich vytahu, ktere nastavime"<<endl;
- cout<<"V "<<i<<" O "<<odkud<<" K "<<kam<<" S "<<smer<<endl;
- pamet[V_POSUN + (i*ARGUMENTU) + V_ODKUD] = odkud;
- pamet[V_POSUN + (i*ARGUMENTU) + V_KAM] = kam;
- pamet[V_POSUN + (i*ARGUMENTU) + V_SMER] = smer;
- pamet[V_POSUN + (i*ARGUMENTU) + V_PATRO] = odkud;
- semaphore_post(semafory,2*pocet_pater+i);
- /*
- cout<<"vypis"<<endl;
- for(int n=0;n<velikost;n++){
- cout<<pamet[n]<<" ";
- }
- cout<<endl;*/
- memory_disconnect(pamet);
- return i;
- }
- sem_post(&semaphores[2*pocet_pater + i]);
- }
- //cout <<"zel nic"<<endl;
- memory_disconnect(pamet);
- // nic nenalezeno -> oznamime to osobe, aby po urcite dobe zkusila zjistit zda je volny nejaky vytah
- return NENALEZEN;
- }
- bool jsme_v_patre(int pamet_id,int vytah,int patro){
- int *pamet;
- pamet = (int *)memory_connect(pamet_id);
- int aktualni_patro;
- aktualni_patro = pamet[V_POSUN + (vytah*ARGUMENTU) + V_PATRO];
- memory_disconnect(pamet);
- if(aktualni_patro == patro){
- return true;
- } else {
- return false;
- }
- }
- void vytah(int vid,const key_t semafory,const int pamet_id){
- int *pamet;
- pamet = (int *)memory_connect(pamet_id);
- int pozice,volno;
- bool start;
- int cislo;
- pozice = V_POSUN + (vid-1)*ARGUMENTU;
- sem_wait(&semaphores[2*pocet_pater + vid]);
- pamet[pozice + V_KAPACITA] = KAPACITA;
- pamet[pozice + V_SMER] = STOJI;
- pamet[pozice + V_PATRO] = 0;
- pamet[pozice + V_KAM] = 0;
- sem_post(&semaphores[2*pocet_pater + vid]);
- while( (pamet[P_STAV] != KONEC) && (pamet[pozice + V_SMER] == STOJI) ){ // cekame na prvotni impuls
- sleep(PRODLEVA);
- }
- start = true;
- while(pamet[P_STAV] != KONEC){
- if( (start) && (pamet[pozice + V_PATRO] != pamet[pozice + V_ODKUD]) ){
- pamet[pozice + V_PATRO] = pamet[pozice + V_ODKUD];
- start = false;
- }
- if(pamet[pozice + V_ODKUD] >pamet[pozice + V_KAM]){
- pamet[pozice + V_SMER] = DOLU;
- }
- if(pamet[pozice + V_ODKUD] < pamet[pozice + V_KAM]){
- pamet[pozice + V_SMER] = NAHORU;
- }
- // sem_wait(&semaphores[2*pocet_pater + vid]);
- sem_wait(&semaphores[2*pocet_pater + vid]);
- if( pamet[pozice + V_PATRO] == pamet[pozice + V_KAM] ){
- // cout<<"Jsem v konecne"<<endl;
- pamet[pozice + V_SMER] = STOJI;
- pamet[pozice + V_ODKUD] = pamet[pozice + V_KAM];
- start = true;
- cout<<"Vytah c."<<vid<<" stoji."<<endl;
- if(pamet[pozice + V_KAPACITA]!= KAPACITA){
- cout<<"!!!!! vytah neni prazdny a stoji !!!!!"<<endl;
- }
- } else {
- sleep(PRODLEVA%2); // nastup
- pamet[pozice + V_PATRO] = pamet[pozice + V_PATRO] + pamet[pozice + V_SMER]; // presun
- }
- /* zajisteni "zaseku", aby vytah nevyjel mimo rozsah */
- if( (pamet[pozice + V_PATRO] > pocet_pater)){
- cout<<"Naraz o horni mantinel."<<endl;
- pamet[pozice + V_SMER] = DOLU;
- //pamet[pozice + V_PATRO] = pocet_pater;
- //pamet[pozice + V_KAM] = pocet_pater;
- //pamet[pozice + V_ODKUD] = pocet_pater;
- }
- if( (pamet[pozice + V_PATRO] < 0) ){
- cout<<"Naraz na spodni mantinel."<<endl;
- pamet[pozice + V_SMER] = NAHORU;
- //pamet[pozice + V_PATRO] = 0;
- //pamet[pozice + V_KAM] = 0;
- //pamet[pozice + V_ODKUD] = 0;
- }
- /*-------*/
- sem_post(&semaphores[2*pocet_pater + vid]);
- /* vypis info o vytahu */
- cout << "Vytah c."<<vid<<endl;
- cout<<"P D F T C"<<endl;
- for(int n=pozice;n<(pozice+ARGUMENTU);n++){
- cout<<pamet[n]<<" ";
- }
- cout<<endl;
- /*----------*/
- sleep(PRODLEVA); // prejezd na dalsi patro
- }
- memory_disconnect(pamet);
- }
- void osoba(int oid,const key_t semafory, const int pamet_id){
- int *pamet;
- pamet = (int *)memory_connect(pamet_id);
- int min,max,odkud,kam,prace, vid,smer,pozice,cas;
- bool nastup = false;
- min = 0;
- max = pocet_pater;
- srand ( time(NULL) );
- odkud = rand() % (max+1);
- while(pamet[P_STAV] != KONEC){
- srand ( time(NULL) );
- prace = rand()%(10+1);
- sleep(prace);
- do {
- srand ( time(NULL) );
- kam = rand() % (max+1);
- } while (odkud == kam);
- if(odkud>kam){
- pozice = pocet_pater + kam;
- smer = DOLU;
- } else {
- pozice = kam;
- smer = NAHORU;
- }
- //printf("Osoba %d pojede z %d. do %d.patra.n",oid,odkud,kam);
- // cesta je vygenerovana
- nastup = false; // uvodni nastaveni
- do {
- if(pamet[P_STAV]==KONEC){ // ukonceni cyklu
- memory_disconnect(pamet);
- return;
- }
- vid = privolat(oid,semafory,pamet_id,odkud,kam);
- while(vid == NENALEZEN){
- if(pamet[P_STAV]==KONEC){
- memory_disconnect(pamet);
- return;
- }
- sleep(PRODLEVA%2);
- vid = privolat(oid,semafory,pamet_id,odkud,kam);
- }
- // cout<<"Osoba "<< oid << " pojede vytahem c."<<(vid)<<endl;
- while( pamet[V_POSUN + (vid*ARGUMENTU) + V_PATRO] != odkud ){
- if(pamet[P_STAV]==KONEC){
- memory_disconnect(pamet);
- return;
- }
- sleep(PRODLEVA%3 );
- }
- //cout<<"Nastupuji do vytahu c."<<(vid)<<endl;
- sem_wait(&semaphores[2*pocet_pater + vid]); // vyhradny pristup pro zmenu kapacity
- pozice = V_POSUN + (vid*ARGUMENTU);
- if ( (pamet[pozice + V_KAPACITA] > 0) && (pamet[pozice + V_PATRO]==odkud) && (pamet[pozice + V_SMER] == smer) ){
- pamet[pozice + V_KAPACITA]--;
- if(smer == NAHORU){
- if(pamet[pozice + V_KAM] < kam){
- pamet[pozice + V_KAM] = kam;
- }
- } else if(smer == DOLU) {
- if(pamet[pozice + V_KAM]> kam){
- pamet[pozice + V_KAM] = kam;
- }
- }
- nastup = true;
- } else {
- nastup = false;
- sem_post(&semaphores[2*pocet_pater + vid]); // vyhradny pristup pro zmenu kapacity
- }
- } while(nastup == false);
- // "nastoupili jsme do vytahu"
- printf("Osoba %d nastoupila do vytahu %d na patre %d. (%d->%d)n",oid,vid+1, odkud,odkud,kam);
- sem_post(&semaphores[2*pocet_pater + vid]); // vyhradny pristup pro zmenu kapacity
- while( (pamet[V_POSUN + (vid*ARGUMENTU) + V_PATRO]!=kam) ){
- if(pamet[P_STAV]==KONEC){// ukonceni cyklu
- memory_disconnect(pamet);
- return;
- }
- sleep(PRODLEVA%4);
- }
- // jsme v pozadovanem patre
- sem_wait(&semaphores[2*pocet_pater + vid]); // vyhradny pristup pro zmenu kapacity
- pamet[V_POSUN + (vid*ARGUMENTU) + V_KAPACITA]++;
- printf("Osoba %d vystoupila z vytahu %d na patre %d. (%d->%d)n",oid,vid+1,kam,odkud,kam);
- sem_post(&semaphores[2*pocet_pater + vid]); // vyhradny pristup pro zmenu kapacity
- odkud = kam;
- }
- memory_disconnect(pamet);
- }
- /*---------------------------*/
- int main(int argc, char *argv[]) {
- //cout<<argc<<endl;
- int pid;
- srand ( time(NULL) );
- switch(argc) {
- case 3 :
- cout<<"zavolano s 3 parametry"<<endl;
- pocet_osob = atoi(argv[1]);
- pocet_pater = atoi(argv[2]);
- pocet_vytahu = 2;
- if( (pocet_osob < 0) || (pocet_pater < 0) ){
- cout << "Se zapornymi cisly nelze pracovat" << endl;
- return 1;
- }
- break;
- case 4 :
- // cout<<"zavolano s 4 parametry"<<endl;
- pocet_osob = atoi(argv[1]);
- pocet_pater = atoi(argv[2]);
- pocet_vytahu = atoi(argv[3]);
- if( (pocet_osob < 0) || (pocet_pater < 0) || (pocet_vytahu<=0)){
- cout << "Se zapornymi cisly nelze pracovat" << endl;
- return 0;
- }
- break;
- default :
- cout << "Ukazka volani : ./vytahy POCET_OSOB POCET_PATER POCET_VYTAHU=2" << endl;
- return 0;
- };
- // vytvoreni sdilene pameti
- seg_id = memory_allocate((pocet_vytahu*ARGUMENTU+1)*sizeof(int));
- int *pamet;
- pamet = (int *) memory_connect(seg_id);
- pamet[0] = START;
- memory_disconnect(pamet);
- // vytvoreni semaforu
- velikost = 2*pocet_pater + pocet_vytahu + ARGUMENTU;
- int semafory_patra;
- semafory_patra = 2*pocet_pater;
- /*semaphore_allocation( klic,velikost,0777);
- for(int i=0;i<velikost;i++){
- semaphore_initialize(klic,i);
- }*/
- semaphores = new sem_t[velikost];
- for(int z=0;z<semafory_patra;z++){
- sem_init(&semaphores[z],1,0);
- }
- for(int m=semafory_patra;m<(velikost);m++){
- sem_init(&semaphores[m],1,1);
- }
- //vytvoreni procesu pro vytahy
- for(int j=0;j<pocet_vytahu;j++){
- pid = fork();
- if(pid == 0){
- // vzniknul podrizeny proces
- //cout<<"Vytvoren podrizeny proces - vytah"<<endl;
- vytah(j+1,klic,seg_id);
- return 0;
- }
- }
- // vytvoreni procesu pro osoby
- for(int k=0;k<pocet_osob;k++){
- pid = fork();
- sleep(3);//zpozdeni vytvareni osob
- if(pid == 0){
- // vzniknul podrizeny proces
- // cout<<"Vytvoreny podrizeny proces - osoba"<<endl;
- osoba(k,klic,seg_id);
- return 0;
- }
- }
- cin.get();
- cin.get();
- // zruseni sdilene pameti
- //int *pamet;
- pamet = (int *) memory_connect(seg_id);
- for(int n=0;n<velikost;n++){
- cout<<pamet[n]<<" ";
- }
- cout<<endl;
- pamet[0] = KONEC;
- memory_disconnect(pamet);
- cout<<"Vypinam procesy..."<<endl;
- sleep(10);
- memory_dealloc(seg_id);
- // zruseni semaforu
- /*
- for(int l=0;l<velikost;l++){
- semaphore_deallocation(klic,l);
- }
- */
- for(int i=0;i<velikost;i++){
- sem_destroy(&semaphores[i]);
- }
- delete [] semaphores;
- return EXIT_SUCCESS;
- }