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.