(related to PR 54185, but for condition_variable_any) As Howard pointed out in c++std-lib-32966 this should work: #include <list> #include <mutex> #include <condition_variable> #include <functional> #include <thread> #include <chrono> #include <cassert> #include <algorithm> 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(); } This test doesn't actually crash with libstdc++, but valgrind shows it's faulty. Fixing this involves replacing std::condition_variable_any::_M_mutex with a std::shared_ptr<std::mutex>
Created attachment 28066 [details] patch against 4.8 trunk
(In reply to comment #1) > Created attachment 28066 [details] > patch against 4.8 trunk That patch needs some additional exports: _ZNSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policy*; _ZNKSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policy*; _ZT[ISV]St16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE;
Fixed for 4.9