2012-10-15 60 views
0

有一個建設區。 100米長的東西方汽車......跨越N/S的行人跨越10米。以下是必須遵守的規則:混亂使用線程和線程技術

如果十字路口是空的,汽車和行人都不應該等待;在單車道路段上,汽車不能同時向相反的方向行駛; 行人不能過馬路的同時在單車道段有一輛車,但 多行人可同時過馬路; 如果有一輛車沿同一方向行駛,汽車可能會進入一個車道區段,但是,汽車不允許經過另一輛車; 一輛汽車不會等兩輛以上的汽車向相反方向行駛; 行人必須屈服於汽車,但行人不應該等待兩輛以上的汽車(在任一方向)。

正在使用的示例文件如下所示:(每一行都是一個獨立的實體,E代表「汽車東行」,W代表西方,P代表行人,第一列是前一個實體的秒數。抵達其現在新實體到達的第三列是速度(每秒米):使用實施例 :

0 E1 10 
1 P1 1 
4 E2 15 
5 W1 10 

目前我代碼被打印出E1進入....(下一行) E1退出......這是重複的,我對使用線程和包含的技術非常困惑,因此此時我被卡住了。我需要更改哪些內容才能打印出正確的順序實體應該到達和離開施工區?所有的幫助表示讚賞。

#include <iostream> 
#include <vector> 
#include <fstream> 
#include <chrono> 
#include <thread> 
#include <random> 
#include <ctime> 
#include <mutex> 
#include <string> 
#include <condition_variable> 

using namespace std; 

class Traffic{ 
    public: 
     void set_time(int a) {prevArrival = a;} 
     void set_name(string a) {name = a;} 
     void set_speed(int a) {carSpeed = a;} 
     int get_time() {return prevArrival;} 
     string get_name() {return name;} 
     int get_speed() {return carSpeed;} 
    private: 
     int prevArrival; 
     string name; 
     int carSpeed; 
}; 

condition_variable_any cE, cW, ped; 
mutex mtx; 

int east=0; //number of cars traveling East currently in the zone 
int west=0; //...traveling West... 
int peds=0; //# of pedestrians crossing the street 

void sleep(int secs); 
void carWest(int time, string name, int speed); 
void carEast(int time, string name, int speed); 
void pedestrian(int time, string name, int speed); 

int main(void){ 
    srand(time(NULL)); 
    ifstream ifs; 
    ofstream ofs; 
    string info, title, temp; 
    int i=0, e=0, w=0, p=0, time, speed; 
    Traffic crossers[50]; 
    vector <thread> eastCars, westCars, pedestrians; 

    ifs.open("traffic.txt"); 
    while (!ifs.eof()){ 
     ifs >> time; crossers[i].set_time(time); 
     ifs >> title; crossers[i].set_name(title); 
     temp = crossers[i].get_name(); 
     if(temp[0] == 'E' || temp[0] == 'e') {e++;} 
     else if(temp[0] == 'W' || temp[0] == 'w') {w++;} 
     else {p++;} 
     ifs >> speed; crossers[i].set_speed(speed); 
     i++; 
    } 
    ifs.close(); 

    for (int i=0; i < e; i++) eastCars.push_back(thread(carEast, crossers[i].get_time(), crossers[i].get_name(), crossers[i].get_speed())); //creating threads 
    for (int i=0; i < p; i++) pedestrians.push_back(thread(pedestrian, crossers[i].get_time(), crossers[i].get_name(), crossers[i].get_speed())); 
    for (int i=0; i < w; i++) westCars.push_back(thread(carWest, crossers[i].get_time(), crossers[i].get_name(), crossers[i].get_speed())); 

    for (thread& t: eastCars) t.join();  // waiting for eastCars, westCars, and pedestrians to finish 
    for (thread& t: pedestrians) t.join(); 
    for (thread& t: westCars) t.join(); 


} 


void pedestrian(int time, string name, int speed) { 
    while(true){ 
     if(name[0] == 'P' || name[0] == 'p'){ 
      if(time == 0 || (east == 0 && west == 0 && peds == 0)) 
       mtx.lock(); 
       cout << name << " entering construction" << endl; 

      while(peds>0 || west>0 || east>0) 
       ped.wait(mtx); 

      peds++; 
      mtx.unlock(); 

      sleep(10/speed); 

      cout << name << " exiting construction" << endl; 
      mtx.lock(); 
      peds--; 
      ped.notify_one(); 
      cE.notify_all(); 
      cW.notify_all(); 
      mtx.unlock(); 
     } 
    } 
} 

void carWest(int time, string name, int speed) { 
    while(true){ 
     if(name[0] == 'W' || name[0] == 'w'){ 
      if(time == 0 || (east == 0 && west == 0 && peds == 0)) 
       mtx.lock(); 
       cout << name << " entering construction" << endl; 

      while(peds>0 || west>0 || east>0) 
       cW.wait(mtx); 

      west++; 
      mtx.unlock(); 

      sleep(100/speed); 

      cout << name << " exiting construction" << endl; 
      mtx.lock(); 
      west--; 
      cW.notify_one(); 
      ped.notify_all(); 
      cE.notify_all(); 
      mtx.unlock(); 
     } 
    } 
} 

void carEast(int time, string name, int speed) { 
    while(true){ 
     if(name[0] == 'E' || name[0] == 'e'){ 
      if(time == 0 || (east == 0 && west == 0 && peds == 0)) 
       mtx.lock(); 
       cout << name << " entering construction" << endl; 

      while(peds>0 || west>0 || east>0) 
       cE.wait(mtx); 

      east++; 
      mtx.unlock(); 

      sleep(100/speed); 

      cout << name << " exiting construction" << endl; 
      mtx.lock(); 
      east--; 
      cE.notify_one(); 
      cW.notify_all(); 
      ped.notify_all(); 
      mtx.unlock(); 
     } 
    } 
} 

void sleep(int secs){ 
    this_thread::sleep_for(chrono::milliseconds(rand()%secs*1000)); 
} 
+0

首先,「if」條件只控制以下語句或塊...嘗試鎖定互斥量然後打印縮進,就像你期望if語句也控制它們一樣。這一切都看起來很不妥,尤其是因爲解鎖是無條件的。你可能會更好地使用在構造函數中鎖定互斥鎖的範圍守護程序,並將其釋放到析構函數中 - 難以弄錯。另外,無鎖 - 您可以在一個'ostringstream'中準備一些輸出,然後在一次操作中將其複製到'cout',並且它將在沒有其他線程輸出的情況下出現。 –

+0

這就是矩陣開始的方式...... – paddy

+0

提示:使用'emplace_back'而不是'push_back'來減少代碼冗餘。 –

回答

0

你的問題是在這裏:

for (int i=0; i < e; i++) eastCars.push_back(thread(carEast, crossers[i].get_time(), crossers[i].get_name(), crossers[i].get_speed())); //creating threads 
for (int i=0; i < p; i++) pedestrians.push_back(thread(pedestrian, crossers[i].get_time(), crossers[i].get_name(), crossers[i].get_speed())); 
for (int i=0; i < w; i++) westCars.push_back(thread(carWest, crossers[i].get_time(), crossers[i].get_name(), crossers[i].get_speed())); 

在你小的數據文件,你有2輛東部汽車,西部1臺車,和一個行人。所以e將是2,而pw將是1. crosser[0]是一輛東汽車

現在,看看那些push_back循環。你正在將crossers [0]添加到所有列表中!因此,您的第一輛(也是唯一)westCar真的是東方汽車。但是你的carWest拒絕做任何工作,除了西方汽車,所以它沒有任何工作。

您可能希望保留完全獨立的列表,而不是將每個人都放在一個crossers列表中。或者你或者可以在你的crossers列表中循環一次,然後檢查name以查看它進入的列表/線程。