2015-12-19 8 views
6

में फंस गया है मेरे पास दो धागे हैं, एक धागा को दूसरे से अनुरोध प्राप्त करना चाहिए और प्रक्रिया करना चाहिए। दूसरा अनुरोधों को स्थानांतरित करना और एक साथ प्रतिक्रिया प्राप्त करना है। मैंने निम्नलिखित योजना की कोशिश की: जोड़ी (मूल्य, वादा) की कतार। पहले धागा एक वादा बनाता है और द्वारा future.get()std :: future.get() कभी-कभी ओएस x

समस्या यह है कि कभी कभी धागा future.get() पर अटक है तुल्यकालिक कतार और एक वापसी मान के लिए इंतज़ार कर में यह धक्का दे दिया, लेकिन जब मैं प्रोग्राम निष्पादन रोक सकते हैं और जारी रखने के लिए इसे फिर से सही ढंग से काम करता है। इस अटकल में यादृच्छिक प्रकृति है।

FutureQueue.h

#ifndef FutureQueue_h 
#define FutureQueue_h 

#include <queue> 
#include <future> 
#include <thread> 
#include <mutex> 
#include <condition_variable> 

template <typename T, typename R> 
class Work{ 
public: 
    Work(){ 

    } 
    Work(T value, std::promise<R>* promise){ 
     m_value = value; 
     m_p_promise = promise; 
    } 
    std::promise<R>* m_p_promise; 
    T m_value; 
public: 
    T getValue(){ 
     return m_value; 
    } 
    void setResult(R result){ 
     m_p_promise->set_value(result); 
    } 
}; 


template <typename T, typename R> 
class FutureQueue 
{ 
public: 
    Work<T,R> getWork(){ 
     auto p = pop(); 
     return Work<T,R>(p.first,p.second); 
    } 
    R execute(T value) 
    { 
     std::promise<R> promise = std::promise<R>(); 
     std::future<R> f = promise.get_future(); 
     auto p = std::pair<T, std::promise<R>*>(value, &promise); 
     push(p); 
     return f.get(); 
    } 
    private: 
    std::pair<T,std::promise<R>*> pop(){ 
     std::unique_lock<std::mutex> mlock(mutex_); 
     while (queue_.empty()) 
     { 
      cond_.wait(mlock); 
     } 
     auto item = queue_.front(); 
     queue_.pop(); 
     return item; 
    } 
    void push(const std::pair<T,std::promise<R>*>& item){ 
     std::unique_lock<std::mutex> mlock(mutex_); 
     queue_.push(item); 
     mlock.unlock(); 
     cond_.notify_one(); 
    } 
    std::queue<std::pair<T,std::promise<R>*>> queue_; 
    std::mutex mutex_; 
    std::condition_variable cond_; 
}; 

#endif 

main.cpp

#include <iostream> 
#include <thread> 

#include "FutureQueue.h" 

using namespace std; 

atomic<bool> quit; 
FutureQueue<int, int> mQueue; 

void consumer(){ 
    Work<int,int> work; 
    while(true){ 
     work = mQueue.getWork(); 
     if (quit){ 
      break; 
     } 
     int value = work.getValue()+100; 
     work.setResult(value); 
    } 
    work.setResult(0); 
} 

int main(int argc, const char * argv[]) { 
    quit = false; 
    thread thread(consumer); 
    // test 2 
    for (int i=0;i<100000;i++){ 
     int value = mQueue.execute(i); 
     cout << "input " << i <<" execute result " << value << endl; 
    } 
    quit = true; 
    mQueue.execute(-1); 
    thread.join(); 
    return 0; 
} 

मैं नहीं जानता कि क्या गलत इस कोड के साथ, हो सकता है आप बेहतर समाधान सुझा सकते हैं। धन्यवाद

अद्यतन

stucks में साथ एप्पल LLVM संस्करण ओएस एक्स केवल तब होता है 6.0

विंडोज

पर
+0

मेरा विजुअल स्टूडियो असफल नहीं होता है, क्या यह एक प्लेटफॉर्म मुद्दा हो सकता है? – mksteve

उत्तर

0

हैं ओएस एक्स और लिनक्स और दृश्य स्टूडियो पर जीसीसी के अंतर्गत कोई समस्या नहीं है दो धागे,

साथ साथ

for (int i=0;i<100000;i++){ 
    int value = mQueue.execute(i); 
    cout << "input " << i <<" execute result " << value << endl; 
} 
quit = true; 
mQueue.execute(-1); 

बी ए

thread thread(consumer); 

आप बी पहले भागो, तो अटक उम्मीद क्योंकि

while (queue_.empty()) 
    { 
     cond_.wait(mlock); 
    } 

बी ए रन तक रन जारी रहेगा कोड

cond_.notify_one(); 

आमतौर पर यह ठीक हो जाएगा के बाद। लेकिन अगर एक पहला मजा "cond.notify_one()", बी कॉल "con_.wait (mlock)", बी हमेशा के लिए अटक जाएगा।

+0

यदि 'ए' पहले चलता है तो कतार खाली नहीं होगी, इसलिए प्रतीक्षा नहीं होगी (और म्यूटेक्स वहां एक दौड़ को रोकता है)। –

+0

एक रन 'cond.notify_one()' से पहले यह 'queue_.push (आइटम) 'कहता है, और बी' cond_.wait (mlock) 'चेक' queue_.empty()' से पहले कॉल करें। मैंने 'cond_.wait (mlock) को बदलने की कोशिश की है;' 'cond_.wait_for (mlock, std :: chrono :: मिलीसेकंड (1)); 'और परिणाम वही – Geka

+0

है यदि आप बदलते हैं" जबकि (queue_.empty()) "करने के लिए" अगर "क्या होगा, यह अभी भी अटक जाएगा? –

संबंधित मुद्दे