Opened 10 years ago
Closed 10 years ago
#7334 closed Bugs (duplicate)
Fix bug concerning condition_variable_any reported in [c++std-lib-32966]
Reported by: | viboes | Owned by: | Anthony Williams |
---|---|---|---|
Milestone: | Component: | thread | |
Version: | Boost 1.51.0 | Severity: | Problem |
Keywords: | Cc: |
Description
the following is ok:
Thread A Thread B ... lk.lock() ... cv.wait(lk) lk.lock() ... cv.notify_one() ... cv.~condition_variable_any() ... lk.unlock() ... ... finally exits cv.wait // ok, not a data race
Below is a complete C++11 HelloWorld that is a simple translation of the example in the POSIX pthread_cond_destroy spec. It should run and not crash or assert:
#include <list> #include <mutex> #include <condition_variable> #include <functional> #include <thread> #include <chrono> #include <cassert> template <class T> class locked_list { std::mutex mut_; std::list<T> list_; public: typedef typename std::list<T>::iterator iterator; typedef typename T::key key; template <class ...Args> void emplace_back(Args&& ...args) {list_.emplace_back(std::forward<Args>(args)...);} iterator find(const key& k) { std::unique_lock<std::mutex> lk(mut_); while (true) { iterator ep = std::find(list_.begin(), list_.end(), k); if (ep == list_.end()) return ep; if (!ep->busy()) { ep->set_busy(); return ep; } ep->wait(lk); } } void erase(iterator i) { std::lock_guard<std::mutex> _(mut_); assert(i->busy()); i->notify_all(); list_.erase(i); } iterator end() {return list_.end();} }; template <class Key> class elt { Key key_; std::condition_variable_any notbusy_; bool busy_; public: typedef Key key; explicit elt(const Key& k) : key_(k), busy_(false) {} bool busy() const {return busy_;} void set_busy() {busy_ = true;} void unset_busy() {busy_ = false;} template <class Lock> void wait(Lock& lk) {notbusy_.wait(lk);} void notify_all() {notbusy_.notify_all();} bool operator==(const Key& k) const {return key_ == k;} }; void f1(locked_list<elt<int>>& list) { auto i = list.find(1); assert(i != list.end()); std::this_thread::sleep_for(std::chrono::milliseconds(500)); list.erase(i); } void f2(locked_list<elt<int>>& list) { auto i = list.find(1); assert(i == list.end()); } int main() { locked_list<elt<int>> list; list.emplace_back(1); std::thread t1 = std::thread(f1, std::ref(list)); std::this_thread::sleep_for(std::chrono::milliseconds(250)); std::thread t2 = std::thread(f2, std::ref(list)); t1.join(); t2.join(); }
If we substitute in boost::condition_variable_any for std::condition_variable_any for the notbusy_ data member of class elt, we get:
Assertion failed: (!pthread_mutex_unlock(m)), function ~interruption_checker, file /Users/hhinnant/Development/boost-dev/boost-trunk/boost/thread/pthread/thread_data.hpp, line 171. Abort trap: 6
Change History (1)
comment:1 by , 10 years ago
Milestone: | To Be Determined |
---|---|
Resolution: | → duplicate |
Status: | new → closed |
Note:
See TracTickets
for help on using tickets.
Duplicated of #7319.