2014-01-13 21 views
1

我正在使用模擬器(ns3),在我的主應用程序中,我分配了幾個名爲Consumer的應用程序以下載一些文件。 在這個類(消費者)中,當我完成下載文件時,我想要登錄一個文件的一些統計信息,所以我使用線程實現了這些功能(下面顯示),如果在我的主體中有少量消費者沒有問題,但是有一個非常大的數字,當我調用創建線程的函數時,我無法打開日誌文件。如何使用線程登錄文件

//consumer.cc 
void 
Consumer::OnData (Ptr<const Data> contentObject) 
{ 
    //do something 
    if (...) 
    { 
    int a = Consumer::create_thread(); 
    std::string s = "foo"; 
    Consumer::Log(s); 
    } 
} 

int Consumer::create_thread(){ 
    int rc = pthread_create(&logger, NULL, &Consumer::runFunc, (void*) this); //logger is declared in consumer.h as pthread_t logger; 
    if(rc) printf("ERROR; return code from pthread_create() is %d\n", rc); 
    sem_init(&queueSem, 0, 0); 
    pthread_mutex_init(&mutex, NULL); 
    //isLogActive = true; 
    myfile.open ("ret.txt", std::ios::app); 
    if(!myfile.is_open()) 
     std::cout << "Error opening the log file..."; 
return 1; 
} 

void Consumer::run_t(){ 
    for(;;) 
    { 
     sem_wait(&queueSem); 
     //if(!isLogActive) 
     // break; 
     pthread_mutex_lock (&mutex); 
     myfile << queue.front(); 
     queue.pop(); 
     pthread_mutex_unlock (&mutex); 
     myfile.flush(); 
    } 
    while(!queue.empty()) 
    { 
       std::cout<<queue.front()<<std::endl; 
     myfile << queue.front(); 
     queue.pop(); 
    }    
    if(myfile.is_open()) 
    { 
     myfile.close(); 
     std::cout << "File Ret closed.\n"; 
    } 
    else 
     std::cerr << "Calcolo error.\n"; 
    pthread_exit(NULL); 
} 

void * Consumer::runFunc(void * self){ 

    ((Consumer*)self)->run_t(); 
    return NULL; 

} 

void Consumer::Log(std::string toLog) 
{ 

    ss.str(""); 
    ss.clear(); 
    ss << toLog << "\n"; 
    pthread_mutex_lock (&mutex); 
    queue.push(ss.str()); 
    pthread_mutex_unlock (&mutex); 
    sem_post(&queueSem); 
} 

您認爲是什麼問題?我怎麼修復它?

回答

1

最有可能的問題是你有多個線程試圖同時追加到文件。這沒什麼好的。

我的建議是有一個日誌記錄線程和一個隊列。當一個線程想寫入日誌時,它只是將消息放在日誌隊列中。日誌記錄線程從隊列中讀取並寫入日誌文件。

當然,您必須向隊列添加一些同步,以便它不會受到併發請求的破壞,或找到已經爲您處理同步的併發隊列。