2015-04-28 33 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次两次。 –