Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ stl unordered_map, thread safety where each thread accesses only it's own assigned key and may edit that value

Here is the scenario:

1) using an unordered_map<int, vector<MyClass*>*> let's say I add keys 1, 2, ... 8
2) all keys are set with a vector at program initialization and nothing more is added or deleted
3) I have 8 threads, where thread1 accesses key[1], thread2 accesses key[2], ... thread8 accesses key[8] (i.e. the thread number can only access that key number and no other key)

Sometimes I re-assign the value vector* to another heap allocated collection. (i.e. thread1 performs key[1] = new vector<MyClass*>)

I believe this will be thread safe, am I correct? If not, I suppose I will use concurrent_unordered_map.

thanks.

like image 724
GreekFire Avatar asked Oct 30 '12 03:10

GreekFire


1 Answers

The answer to this question can be found in [res.on.data.races]/3:

A C++ standard library function shall not directly or indirectly modify objects (1.10) accessible by threads other than the current thread unless the objects are accessed directly or indirectly via the function’s non- const arguments, including this.

Furthermore, [container.requirements.dataraces]/1 states:

For purposes of avoiding data races ([res.on.data.races]), 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[].

Since unordered_map::operator[] is non-const, it is legal for an implementation to modify the unordered_map when a call to operator[] occurs. You should instead use unordered_map::find, which is explicitly required to be treated as const, and hence will not modify the unordered_map:

map.find(key)->second = new vector<MyClass*>;

(As a side note, your suggested design looks like a recipe for memory leaks. Why not make it be a unordered_map<int, std::unique_ptr<vector<MyClass*>>>, or unordered_map<int,vector<MyClass*>>?)

like image 116
Mankarse Avatar answered Sep 21 '22 08:09

Mankarse