Subject: [Boost-bugs] [Boost C++ Libraries] #7334: Fix bug concerning condition_variable_any reported in [c++std-lib-32966]
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2012-09-06 04:19:24
#7334: Fix bug concerning condition_variable_any reported in [c++std-lib-32966]
------------------------------+---------------------------------------------
Reporter: viboes | Owner: anthonyw
Type: Bugs | Status: new
Milestone: To Be Determined | Component: thread
Version: Boost 1.51.0 | Severity: Problem
Keywords: |
------------------------------+---------------------------------------------
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
}}}
-- Ticket URL: <https://svn.boost.org/trac/boost/ticket/7334> Boost C++ Libraries <http://www.boost.org/> Boost provides free peer-reviewed portable C++ source libraries.
This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:10 UTC