c++ - Boost condition variable -
i use boost condition variable synchronization mechanizm, in case:
boost::condition_variable cond; boost::mutex mutex; void worker_func() { cond.notify_all(); std::cout << "after notify" << std::endl; } void main() { boost::mutex::soped_lock lock(mutex); boost::thread work(worker_func); boost::this_thread::sleep_for(boost::chrono::milliseonds(500)); cond.wait(lock); // here deadlock }
when 'fire' condition before wait condition there deadlock. if there solution write wrapper provide bool atomic 'remember' condition fired or there other better way ?
example of wrapper:
class cond_wrap { private: boost::condition_variable cond; boost::mutex mutex; bool work_to_do; public: cond_wrap() { boost::mutex::scoped_lock(mutex); work_to_do = false; } void notify_all() { boost::mutex::scoped_lock(mutex); work_to_do = true; cond.notify_all(); } void wait() { boost::mutex::scoped_lock lock(mutex); if(!work_to_do) { cond.wait(lock); work_to_do = true; } else { return; } } bool timed_wait(unsigned int timeout) { boost::mutex::scoped_lock lock(mutex); if(!work_to_do) { if(cond.timed_wait(lock, boost::chrono::milliseonds(timeout))) { work_to_do = true; return true; } else { return false; } } else { return false; } }; cond_wrap condition_wrap; void worker_func() { { condition_wrap.notify_all(); } std::cout << "after notify" << std::endl; } int main() { boost::thread work(worker_func); work.detach(); { boost::this_thread::sleep_for(boost::chrono::milliseonds(500)); condition_wrap.wait(); //there work } return 0; }
that's not how condition variables work. condition variable should have condition associated. condition evaluated mutex held, no races possible, , don't need wait.
note condition needed possibility of spurious wake-ups.
also condition variable should notified thread holds lock. , not idea spawn new threads lock held. add braces state scope of locked code.
boost::condition_variable cond; boost::mutex mutex; bool work_to_do = false; void worker_func() { { boost::mutex::scoped_lock lock(mutex); work_to_do = true, cond.notify_all(); } std::cout << "after notify" << std::endl; } int main() { boost::thread work(worker_func); { boost::mutex::scoped_lock lock(mutex); boost::this_thread::sleep_for(boost::chrono::milliseonds(500)); while (!work_to_do) cond.wait(lock); // no deadlock //there work work_to_do = false; } }
note how in code work_to_do
variable used lock held, call notify_all()
. also, note cond.wait()
called in loop, spurious wake-ups not spoil fun.
ps. no void main()
.
Comments
Post a Comment