2013-10-06 4 views
0

질문 1 : 각 스레드를 프로그램 전체에서 사용할 수 있도록 이름을 지정하려고하지만 '비행기'[t] '의 멤버'fid '요청과 같은 오류가 발생합니다. 'pthread_t'클래스가 아닌 클래스입니다. 이것은 평면 [t] .tid 또는 평면 [t] .startState의 사용을 참조합니다. 각 개별 스레드에 대해이 값을 얻거나 저장하는 방법을 잘 모르겠습니다. .프로그램을 통해 스레드에 대한 정보에 액세스하는 방법

질문 2 :. 내가 스레드의 startState이되면 어떻게 이륙() 함수 (스위치 상태와 printfs의 시리즈) 스레드를 보낼 수 있습니다

질문 3 : startState에 전달해야합니까 함수? 각 스레드는 시작 상태를 기억하도록 노력하고있어 늦게 코드에서 r은 내가 비행 "착륙"또는 될 수 있습니다 여기에

는 관련 코드는 "이륙." 10/06 업데이트 22시 37분에서

#include <pthread.h> 
#include <stdio.h> 
#include <cstdlib> 
#include <iostream> 
#include <queue> 
#include <unistd.h> 
#include <algorithm> 
#include <time.h> 
#include <ctime> 

#define NUM_THREADS 3  //3 flights 

using std::queue; 
using std::vector; 

pthread_mutex_t runway1lock; 
pthread_mutex_t runway2lock; 

bool run1occupied; 
bool run2occupied; 

struct flight_data{     //each plane has these characteristics 
     //void *FlightID; 
    long fid; 
     int startState;  // if start=1 ==> taking off :::  if start=2 ==> landing 
     int flyTime;   //fly == randomly generated time (order) of takeoff/land     
}; 

struct flight_data flightinfo[NUM_THREADS]; 

void *FlightID(void *flightid){ 
     struct flight_data *my_flights; 
     my_flights = (struct flight_data*)flightid; 
     int taskid; 
     taskid = my_flights->fid; 
//  long fid; 
    //  fid = (long)flightid; 
//  printf("Flight #%1d\n", tid); 
     pthread_exit(NULL); 
} 

void Start(struct flight_data my_flights){ 
     my_flights = (struct flight_data)my_flights; 
     int startState; 
    srand(time(0)); 
    my_flights.startState = rand() % 2+1; 
     std::string startstring; 
     if(my_flights.startState == 1){ 
       startstring = "Taking off"; 
     } 
     if(my_flights.startState == 2){ 
       startstring = "Landing"; 
     } 
    for(int i = 1; i<NUM_THREADS+1; i++){ 
      std::cout << "Start state for Flight # " << i << " is " << startstring << std::endl; 
    } 
} 

void takeoff(struct flight_data my_flights){ 
    my_flights = (struct flight_data)my_flights;  
    for(int i = 1; i<NUM_THREADS+1; i++){ 
     int state = my_flights.startState; 
     switch(state){ 
      case 1:{  //G (GATE) 
       std::cout << "Flight # " << flightinfo[i].fid << " is listed as waiting at the gate." << std::endl; 
       std::cout << "Flight # " << flightinfo[i].fid << "'s position in queue for runway: " << flightinfo[i].flyTime << std::endl; 
       sleep(3); 
       state = 2; 
       break; 
      } 
      case 2: {  //Q (queue) -- sets order for use of runway 
       queue<pthread_t> queue; 
       vector<int> flightTimes;  
       int soonestFlightTime = 10; 
       flightTimes.push_back(flightinfo[i].flyTime);   //put all flight times into a vector called flightTimes 
       std::sort(flightTimes.begin(), flightTimes.end());  //sort the vector of flightTimes low to high 
       std::reverse(flightTimes.begin(), flightTimes.end());  //flips vector -- high(front) to low(back) 
       while(!flightTimes.empty()){ 
        if (flightinfo[i].flyTime == flightTimes.back()){ //if a thread has the soonest flight time 
         queue.push(i);  //then put the flight in the runway queue 
         flightTimes.pop_back();  //pop off the soonest flight time 
        } 
       } 
       while(!queue.empty()){ 
        if(flightinfo[i].fid == queue.front()){ 
         state = 3; 
         queue.pop(); 
         sleep(3); 
        } 
       } 
       break; 
      } 
      case 3: {  //CLR (clearance for runway) 
       std::cout << "Flight # " << flightinfo[i].fid << " has clearance to move to the runway." << std::endl; //will go in order of queue 
       if(run1occupied){ 
        sleep(3); 
       } 
      // else if(collide){ 
      //  state = 7; 
      // } 
       else{ 
        state = 4; 
       } 
       break;  
      } 
      case 4: {  //RTO (runway takeoff) 
       pthread_mutex_lock(&runway1lock); 
       run1occupied = true; 
       std::cout << "Flight # " << flightinfo[i].fid << " is taking off. Runway occupied. Stand by." << std::endl; 
       sleep(3); 
       pthread_mutex_unlock(&runway1lock); 
       run1occupied = false; 
       state = 5; 
       break; 
      } 
      case 5: {  //CZ (cruise) 
       std::cout << "Flight # " << flightinfo[i].fid << " is reaching proper altitude and cruising toward destination." << std::endl; 
       sleep(3); 
      // if(!collide){ 
        state = 6; 
      // } 
      // else{ 
      //  state = 7; //collision!!! 
      // } 
       break; 
      } 
      case 6: {  //RMV (remove from monitoring list) 
       std::cout << "Flight # " << flightinfo[i].fid << " has been removed from the monitoring list." << std::endl; 
       break; 
      }  
      case 7:{  //COLL (collision) 
       std::cout << "Collision in the air. There were many casualties." << std::endl; 
       break; 
      } 
     } 
    } 
} 

void landing(struct flight_data my_flights){ 
    my_flights = (struct flight_data)my_flights; 
    for (int i = 0; i<NUM_THREADS; i++){ 
     int state = my_flights.startState; 
     switch(state){ 
      case 1:{  //ENTR (enter monitoring list) 
       state = 2; 
       break; 
      } 
      case 2:{  //Q (queue) 
       //if not the first thing in the queue then state = 4; 
       //otherwise state = 3; 
      } 
      case 3:{  //RWL (runway land) 
       state = 5; 
       break; 
      } 
      case 4:{  //HVR (hover) 
       //if first in queue then state = 3; 
       //otherwise stay here 
       //if collision state = 7; 
      } 
      case 5:{  //CLR (clearance to move to gate) 
       //if collision state = 7 
       //otherwise state = 6; 
      } 
      case 6:{  //G (gate) 

      } 
      case 7:{  //COLL (collision) 

      } 
     } 
    } 
} 

/* 
bool collision(){ 
    bool collide; 
    //random 
    if(){ 
     collide = true; 
    } 
    else{ 
     collide = false; 
    } 
    return collide; 
}*/ 

int main(int argc, char *argv[]){ 
     pthread_t flights[NUM_THREADS];   //pthread_t keeps a thread ID after the thread is created with pthread_create() 
               //it's like an index on a vector of threads 
     int *taskids[NUM_THREADS]; 
     int rc; 
     long t; 
     for (t=1; t<=NUM_THREADS; t++){         //loop creates threads(flights) 
       printf("In main: Creating flight %1d\n", t); 
       flightinfo[t].fid= t; 
       rc = pthread_create(&flights[t], NULL, FlightID, (void *)&flights[t]); 
       if (rc){ 
         printf("ERROR: return code from pthread_create() is %d\n", rc); 
         return (-1); 
       } 
       printf("Created flight %1d\n", t); 
     //  Start(flightinfo[t]); 
       flightinfo[t].startState = rand() % 2+1; 
       std::cout << flightinfo[t].startState << std::endl; 
       if((flightinfo[t].startState)==1){ 
         std::cout << "Flight # " << flightinfo[t].fid << " is listed with start state as " << flightinfo[t].startState << std::endl; 
         takeoff(flightinfo[t]); 
         //go to takeoff function and go through switch case  
       } 
       if((flightinfo[t].startState)==2){ 
         std::cout << "Flight # " << flightinfo[t].fid << " is listed with start state as " << flightinfo[t].startState << std::endl; 
         landing(flightinfo[t]); 
         //go to landing function and go through switch case  
       } 
     } 
     pthread_exit(NULL); 
} 
+0

이 소스를 약간 정리하는 것이 좋습니다. 첫 번째 변경은 무효를 취한 후 실제 유형으로 변환하는 대신 인수 목록에서 실제 유형 이름으로 void를 대체하는 것입니다. 컴파일러는 친구이자 첫 번째 방어 수준이므로 가능한 한 정적 오류 검사에 사용하십시오. –

+0

@ 리차드 : 당신은 * 할 수 없습니다. 타입 소거는'pthread_create'에 전달 된 컨텍스트 변수와 스레드 프로 시저에 필요합니다. 음, 스레드 프로 시저로 설계된 두 가지 기능이있는 것처럼 보이기 때문에 혼란 스럽지만 그 중 하나만 사용됩니다. –

+0

@BenVoigt, StartState(). –

답변

0

그 모든 변수가 표시 planes 어레이가 아닌 flights 어레이에 저장됩니다.

1

pthread_t 관리 변수 planes과 비행 데이터가 포함 된 변수 flights이 혼동스러워 보입니다.

pthread_t 관리 변수 planes은 pthread 라이브러리에서 사용하며 실제로는 pthread 라이브러리 호출의 인수로만 사용해야합니다. 그렇지 않으면 그냥두면 고사하고 걱정하지 않아도됩니다. 변수 planes을 작성한 다음 pthread 라이브러리에 사용하여 제공하는 저장 영역으로 생각하십시오. 그렇게하면 pthread 라이브러리에 해당 변수의 소유권을 부여 할 수 있습니다.

따라서 비즈니스의 첫 번째 순서는 pthread 관리와 스레드가 조작하고있는 실제 데이터의 차이를 구분하는 것입니다.

pthread 관리 변수 인 planes을 여러 곳에서 비행 데이터 변수처럼 사용하고 있습니다. 그렇지 않습니다. 이해가되지 않는 기능 StartState()flights

 if((flights[t].startState)==1){ 
       std::cout << "Flight # " << flights[t].fid << " is listed as waiting at the gate." << std::endl; 
       void takeoff(); 
       //go to takeoff function and go through switch case  
     } 
     if((flights[t].startState)==2){ 
       std::cout << "Flight # " << flights[t].fid << " is listed as waiting to land." << std::endl; 
       //go to landing function and go through switch case  
     } 

와 소스의이 비트를 planes를 교체합니다.

for(int i = 0; i<NUM_THREADS; i++){ 
     startState = rand() % 1+2; 
} 
startState = my_flights->startState; 

임의의 시작 상태로 특정 비행의 시작 상태를 설정하려고한다고 가정합니다. 그래서 당신은 특정 비행을위한 시작 상태를 설정하는데 관심이 있고 루프는 난수 생성기를 연습하는 것 외에는 아무것도하지 않는다고 가정 할 때 소스가 다음과 같이 보이기를 기대합니다. NUM_THREADS 번 루프가 다음과 같은 것. 그러나 이것에 대한 당신의 논리와 그 범위가 정확한지 또는 다른지에 대해서는 확인하지 못했습니다.

my_flights->startState = rand() % 1+2; 

는 조금 프로그램이나 응용 프로그램을 것으로 작업

당신은 스레드를 생각해야한다의 과정을 제안했다. 이 간단한 예제에서는 먼저 스레드에 대한 걱정없이 비행 논리를 작성하는 것이 좋습니다.그래서 함수로 시작한다면, 비행 변수를 전달하는 FlyPlaneFlight()이라고 말하면,이 함수는 다양한 함수를 호출하여 다양한 함수를 호출하고, 비행이 끝나면 호출자에게 돌아옵니다. 그러면 함수 호출을위한 좋은 장소에있을 것입니다. 스레드. 단일 비행을위한 논리를 갖추면 pthread 라이브러리를 사용하여 비행 데이터를 초기화 한 다음 FlyPlaneFlight()을 사용하는 스레드를 생성하여 여러 개의 비행을 생성합니다.

또한 시간과 상호 작용을 고려해야합니다. 이런 종류의 시뮬레이션을 위해 FlyPlaneFlight() 함수에 루프 데이터를 변경 한 다음 스레드가 2 ~ 2 초 동안 잠자기 상태가되도록하는 것이 좋습니다. 초보 테스트로, 반복 명확한 숫자로 루프를 사용하고 다음과 같은 종료됩니다 :

for (int i = 0; i < 100; i++) { 
    // modify the flight data 
    sleep(1000); // sleep for a second (1000 milliseconds) then repeat 
} 

비행 독립 아니지만 어떤 방법으로 동기화해야합니다 있도록이 더 복잡하게하는 경우 , pthread 라이브러리의 스레드 동기화 기능을 조사해야합니다. 당신이 pthread_create() 기능으로 FlyPlaneFlight() 기능을 포장 할 때

그래서, 다음과 같은 소스 싹둑처럼 보일 수 있습니다

void *FlightID(void *flightdata){ 
    struct flight_data *my_flights = (struct flight_data*)flightdata; 

    // initialize the flight data as needed 
    FlyPlaneFlight (myFlight); 
    // print out the myFlight data so that you can see what happened 
    pthread_exit(NULL); 
} 

아이디어는 필요한 데이터의 평면 개체로 비행을 모두 치료하는 것입니다 비행은 struct flight_data 구조체에 있으며, 대부분의 경우 실제 비행 시뮬레이션과 관련이없는 pthread 라이브러리를 무시할 수 있지만 여러 개의 비행 객체 시뮬레이션을 허용하는 데 사용됩니다. 따라서 각각의 고유 한 비행 데이터가있는 다중 스레드를 만든 다음 동일한 코드를 사용하여 비행 데이터를 처리합니다. 다양한 비행이 서로 다른 역사를 가질 수 있도록 약간의 무작위 배정을합니다. 그들은 다른 일을 할 것입니다.

편집

메인은 다음

for (t=0; t<NUM_THREADS; t++){     //loop creates threads(flights) 
    std::cout << "In main: Creating flight " << t+1 << std::endl; 
    flights[t].fid= t+1; 
    rc = pthread_create(&planes[t], NULL, FlightID, (void *)&flights[t]); 
    if (rc){ 
     std::cout << "ERROR: return code from pthread_create() is " << rc << std::endl; 
     return (-1); 
    } 
    std::cout << "Created flight " << t << std::endl; 
} 
pthread_exit(NULL); // exit the main thread and allow remaining threads to complete 

이것은 당신의 다양한 스레드를 생성하고 실행하게됩니다 같은 루프 뭔가있을 것입니다. FlyPlaneFlight() 함수의 루프에서 루프를 통해 매번 다음과 같은 상태를 출력 할 수 있으므로 FlyPlaneFlight() 함수는 비슷한 모양을 가지며 finite state machine의 종류를 사용하여 임의의 숫자를 사용하여 상태로 이동할 수 있습니다. 에서는 22시 37분

에서 소스 업데이트 10/06에 기초

void FlyPlaneFlight (struct flight_data *my_flights) 
{ 
    for (int i = 0; i < 100; i++) { 
     switch (my_flights->startState) { 
      case 1: 
       std::cout << "Flight # " << my_flights->fid << " is listed as waiting at the gate." << std::endl; 
       // now move the flight state to the next state. 
       break; 
      case 2: 
       std::cout << "Flight # " << my_flights->fid << " is listed as waiting to land." << std::endl; 
       // now move the flight state to the next state. 
       break; 
      // other case statements for other flight states and moving between the 
      // various flight states. 
     } 
     sleep (1000); // sleep this thread for one second (1000 milliseconds) then repeat 
    } 
} 

EDIT # 2 : 발전기는 다음 상태를 결정하거나, 현재 상태를 유지하도록 rand() function as in these examples를 사용하여 가상 주사위 롤 귀하의 소스는 글로벌 배열 변수입니다., 소스를 통해 직접 액세스하려고합니다. 이것은 당신을 문제로 이끌고있는 실수입니다. 당신이해야 할 일은 스레드가 특정 스레드에 대한 특정 배열 요소를 할당하도록 호출을 생성하게하는 것입니다. 그 때 비행 배열에 대해 걱정하지 않고 그 스레드에 할당 된 특정 요소 만 사용하십시오.

예를 들어 다음과 같이 스레드 생성을 사용하여 스레드를 생성하고 생성되는 스레드에 고유 한 배열 요소를 할당합니다.그 시점에서 flights[t]에 비행 데이터에서 작동 당신의 기능 중 하나가 바로 그 배열 요소에 그 포인터를 사용할 수 있도록

rc = pthread_create(&planes[t], NULL, FlightID, (void *)&flights[t]); 

스레드 항목 기능은 FlightID()는 인수로 해당 배열 요소에 대한 포인터를 받아들입니다. 기능은 특정 비행에 대해서만 걱정해야하며 다른 모든 비행에 대해서도 걱정해서는 안됩니다.

스레드가 시작된 후에도 함수 FlightID()과이 함수가 호출하는 함수는 더 이상 다른 스레드에 대해 염려하지 않아야하므로이 함수에있는 NUM_THREADS의 모든 루프가 없어야합니다.

아이디어는 특정 비행에서 작동하는 FlightID()을 호출하여 시작되는 작은 프로그램을 갖는 것입니다. 그런 다음 여러 스레드에서 각 스레드는 FlightID()에서 시작합니다. 이것은 main()이 C/C++ 프로그램의 진입 점이라는 아이디어와 비슷합니다. main()에 인수가 있고 프로그램이 main()에서 시작됩니다. 스레드의 경우 스레드는 스레드 입력 함수에서 시작합니다.이 함수는 FlightID()입니다.

FlyPlaneFlight()에 루프가있는 이유는 특정 비행에 대한 유한 상태 기계에 일련의 상태 변경을 제공하기 위해서입니다. 다시 말해서 루프 안쪽에있는 것은 비행기 편입니다.

제안 된 스레드 생성 루프와 사용자의 스레드 생성 루프의 차이점을 살펴보십시오. 내 스레드는 스레드를 만드는 것 이상을 수행하지 않습니다. 귀하의 스레드를 생성하고 정말로 지금은 스레드가 아니라 주 생성에 속해야 비행 배열 요소와 함께 일을하려고합니다.

+0

당신의 포스트는 저에게 대단히 도움이되었습니다. 나는 지금 내가 원래 가지고있는 것을 업데이트했다. rand()와 srand()는 나에게 힘든 시간을 주었고, 그래서 나는 현재 주석 달기를 시작했고 메인에서 직접 rand()를 사용하고있다. 이제 ... 프로그램이 다시 실행됩니다 (만세!)하지만 스레드 1과 2 만 메인에서 빠져 나와 프로그램이 실행되고 실행되지만 다른 것은 발생하지 않습니다. 내가 볼 수 없다는 것을 당신이 보는 무엇이라도? – Anna

+0

@Anna, 소스를 업데이트 한 것 같습니다. 그것을 나타 내기 위해 편집을 할 것입니다. 당신의 소스에서 당신이해서는 안되는 몇 군데에서 NUM_THREADS에 대한 루프가 있습니다. NUM_THREADS가 필요한 유일한 곳은 스레드를 시작할 때입니다. 다른 장소는 특정 스레드의 소스 일 뿐이며이 소스는 각 스레드에 의해 재사용됩니다. –

+0

@Anna, 예제에서 FlyPlaneFlight() 함수에는 NUM_THREADS에 대한 루프가 없습니다. 코드에서 NUM_THREADS가있는 루프가있는 유일한 위치는 다양한 스레드를 시작할 때입니다. 다른 기능들은 한 번에 한 비행에서 작동하며 그들이 작업하고있는 비행 이외의 다른 것에 대해서는 알지 못합니다. 내가 제공하는 것과 같은 방법을 사용하여 단일 비행편에 대해 이것을 작성하는 것이 가장 좋습니다. –

관련 문제