Reputation: 30605
I am using visual studio and I keep getting an exception on the following line of the boost::shared_ptr code:
void release() // nothrow
{
if( BOOST_INTERLOCKED_DECREMENT( &use_count_ ) == 0 )
{
dispose();
weak_release();
}
}
I think it is multithreading because it is very random when it occurs.I'm struggling to get more details.
I share an unordered_map<std::string, boost::shared_ptr<MyClass>>
amongst several threads. I think the error is due to different threads accessing the unordered_map at the same time (the threads don't access the same elements of the unordered_map).
MyClass contains an unordered_map and a set. The threads add numbers to these data structures. So if I had:
class MyClass{
public:
void addToMap(double a, long b);
void addToSet(double c);
private:
unordered_map<double, long> a;
set<double> b;
}
std::unordered_map<std::string, boost::shared_ptr<MyClass> >
std::unordered_map<std::string, boost::shared_ptr<MyClass> >
std::unordered_map<std::string, boost::shared_ptr<MyClass> >
std::unordered_map<std::string, boost::shared_ptr<MyClass> >
I do not have any locks in my code. Could someone please advise how I could potentially solve this problem (even if it means making the code slower)? Do I just need to insert mutexes inside each MyClass object? However it seems to be the boost::shared_ptr of the MyClass object which is causing the exception?
I do not pass any boost::shared_ptr
objects by reference/pointer.
Upvotes: 0
Views: 249
Reputation: 42544
operator[]
modifies the container, and is therefore not safe to access concurrently. Your program has a data race. Generally, non-const
member functions of standard library objects are not safe for simultaneous access. C++11 §23.2.2 lists some special exceptions for containers:
1 For purposes of avoiding data races (17.6.5.9), implementations shall consider the following functions to be
const
:begin
,end
,rbegin
,rend
,front
,back
,data
,find
,lower_bound
,upper_bound
,equal_range
,at
and, except in associative or unordered associative containers,operator[]
.2 Notwithstanding (17.6.5.9), implementations are required to avoid data races when the contents of the contained object in different elements in the same sequence, excepting
vector<bool>
, are modified concurrently.
So for unordered_map
, it's unsafe for multiple threads to simultaneously call operator[]
- but it is safe for them to access distinct objects in the container simultaneously. Protecting the lookup of elements is sufficient, e.g.:
std::unique_lock<std::mutex> lk(some_mutex);
auto& foo = my_map["key"];
lk.unlock();
foo += 42;
Alternatively, if you only want to access existing elements in the map - and not add new default constructed elements - you can use find
without external synchronization per the standard quote above.
Upvotes: 2