public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug libstdc++/54352] New: relaxed data race rules for ~condition_variable_any
@ 2012-08-22 20:29 redi at gcc dot gnu.org
2012-08-22 20:43 ` [Bug libstdc++/54352] " redi at gcc dot gnu.org
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: redi at gcc dot gnu.org @ 2012-08-22 20:29 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54352
Bug #: 54352
Summary: relaxed data race rules for ~condition_variable_any
Classification: Unclassified
Product: gcc
Version: 4.8.0
Status: UNCONFIRMED
Keywords: ABI
Severity: normal
Priority: P3
Component: libstdc++
AssignedTo: unassigned@gcc.gnu.org
ReportedBy: redi@gcc.gnu.org
(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>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2013-07-21 19:25 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-22 20:29 [Bug libstdc++/54352] New: relaxed data race rules for ~condition_variable_any redi at gcc dot gnu.org
2012-08-22 20:43 ` [Bug libstdc++/54352] " redi at gcc dot gnu.org
2012-08-22 20:58 ` redi at gcc dot gnu.org
2013-07-21 19:25 ` redi at gcc dot gnu.org
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).