Std :: future.get () sometimes gets stuck in os x

I have two threads, one thread must receive and process requests from the other. The second is sending requests and receiving a response synchronously. I tried the following scheme: pair queue (value, promise). The first thread creates a promise and pushes it into the synchronous queue and waits for the return value of future.get()

The problem is that sometimes the thread gets stuck in future.get() , but when I pause the program and continue it, it works correctly. this little thing is random.

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; } 

I do not know what is wrong with this code, maybe you can offer a better solution. thank you

UPDATE

Stucks only happens on os x with Apple LLVM version 6.0

No problem under gcc on OS X and Linux and Visual Studio on Windows

+6
source share
1 answer

There are two streams: A with

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

B s

 thread thread(consumer); 

You expect B to start first and then stuck because

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

B will continue to execute until A runs the following code

  cond_.notify_one(); 

This is usually normal. But if the first pleasure is "cond.notify_one ()", then calling B "con_.wait (mlock)", B will be stuck forever.

0
source

All Articles