2015-04-28 32 views
3

我開始學習多線程,並遇到了通過共享資源同步線程的期貨和承諾。所以,我想到使用Futures和Promises(單一生產者和單一消費者)實施一個着名的Double Buffering問題。 的基本方法是什麼我想到的是:使用C++實現使用期貨和承諾的雙緩衝11

ProducerThread:

loop:  
    locks_buffer1_mutex  
    fills_buffer1 
    unlocks_buffer1_mutex  
    passes number 1 to Consumer thread using promise.setvalue()  
    locks_buffer2_mutex  
    fills_buffer2 
    unlocks_buffer2_mutex  
    passes number 2 to Consumer thread using promise.setvalue() 
back_to_loop 

ConsumerThread:

loop: 
    wait_for_value_from_promise 
    switch 
     case 1: 
     lock_buffer1_mutex 
      process(buffer1) 
     unlock_buffer1_mutex 
     print_values 
     break 
     case 2: 
     lock_buffer2_mutex 
     process(buffer2) 
     unlock_buffer2_mutex 
     print_values 
     break 
back_to_loop 

下面是代碼:

#include <iostream> 
#include <thread> 
#include <vector> 
#include <future> 
#include <mutex> 
#include <iterator> 


std::mutex print_mutex; 
std::mutex buffer1_mutex; 
std::mutex buffer2_mutex; 

std::vector<int> buffer1; 
std::vector<int> buffer2; 

bool notify; 


void DataAcquisition(std::promise<int> &p) 
{ 
    std::this_thread::sleep_for(std::chrono::seconds(2)); 
    while(true) 
    { 
     { 
      std::lock_guard<std::mutex> buff1_lock(buffer1_mutex); 
      for(int i=0;i<200;i++) 
      { 
       buffer1.push_back(i); 
      } 
     } 
     p.set_value(1); 
     { 
      std::lock_guard<std::mutex> buff2_lock(buffer2_mutex); 
      for(int i=0;i<200;i++) 
      { 
       buffer2.push_back(199-i); 
      } 
     } 
     p.set_value(2); 
    } 
} 

void DataExtraction(std::future<int> &f) 
{ 
    std::vector<int>::const_iterator first,last; 
    std::vector<int> new_vector; 
    std::ostream_iterator<int> outit(std::cout, " "); 

    while(true) 
    { 
     int i = f.get(); 
     std::cout << "The value of i is :" << i << std::endl; 
     switch(i) 
     { 
      case 1: 
       { 
        std::lock_guard<std::mutex> buff1_lock(buffer1_mutex); 
        first = buffer1.begin(); 
        last = first + 10; 
       } 
       new_vector = std::vector<int>(first,last); 
       { 
        std::lock_guard<std::mutex> print_lock(print_mutex); 
        std::copy(new_vector.begin(),new_vector.end(),outit); 
       } 
       break; 
       case 2: 
       { 
        std::lock_guard<std::mutex> buff2_lock(buffer2_mutex); 
        first = buffer2.begin(); 
        last = first + 10; 
       } 
       new_vector = std::vector<int>(first,last); 
       { 
        std::lock_guard<std::mutex> print_lock(print_mutex); 
        std::copy(new_vector.begin(),new_vector.end(),outit); 
       } 
       break; 
      } 
    } 
} 

int main() 
{ 
    std::promise<int> p; 
    std::future<int> f = p.get_future(); 


    std::thread thread1(DataAcquisition,std::ref(p)); 
    std::thread thread2(DataExtraction,std::ref(f)); 

    thread1.join(); 
    thread2.join(); 

    return 0; 
} 

當我執行此代碼我碰到他通過giagntic問題,我完全不知道

terminate called after throwing an instance of 'std::future_error' terminate called recursively 
    what(): 0 1 2 3 4 5 6 7 8 9 Promise already satisfied 
Press <RETURN> to close the window 

我用Google搜索這個錯誤,建議在連接過程中鏈接-lpthread開關和編譯時間。但無法解決問題。

請幫助我,我要去哪裏錯了..

+0

對於你想要做的事情,原子不足以指示最近完成的緩衝區?請注意,「消費者」不能保證「製片人」製作的所有幀。如果您想象'打印值'很慢,那麼很容易直觀地看到。消費者在「印刷價值」期間沒有鎖定,「製片人」可能會產生任何數量的幀並且寫出它們。即使您不介意「丟幀」,更微妙的合作意味着您不會浪費CPU週期來產生無人能見的輸出。 – Persixty

+0

通過類似的參數'Consumer'可能會處理相同的幀兩次。 – Persixty

回答

3

不能調用set_valuepromise更多的一次,這是由下面的代碼所示:

#include <future> 

int main() { 
    std::promise<int> p; 
    p.set_value(1); 
    p.set_value(2); // Promise already satisfied 
} 

你必須尋找另一種方法。例如,您可以使用兩個std::condition_variable - 將它們設置爲生產者,並在消費者中等待它們。

+0

嗨安東,你的意思是我們不能在整個執行過程中不止一次地在一個promise上調用set_value ......?你提出的關於閱讀緩衝區的建議「反過來」,我無法確切地得到你要求我做的事情。 – jeldikk

+1

@ user1511151是的,一旦設置了值,就不能再做了。關於「反過來」看來它不會很容易工作,你可以使用條件變量,看看我的更新。 –

+0

對,承諾只是一個價值+時間,一旦價值在那裏就不可能再次設置 - 這就像試圖設置5次兩次。 –