Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> And unlike with vectors, I don’t know that I’ve ever come across code that retained map iterators…

I've done this once. The thing I was trying to do was have multiple threads write to a std::unordered_map in such a way that each thread would write to its allocated "bucket" and nothing else (roughly, each thread would "own" map[thread_id] as a somewhat convoluted "thread local storage" which would then be collected and operated on at some point in the future from the "master" thread). It turns out that to the only way to actually do this in a standards-compliant way is to grab an iterator pointing to map.find(thread_id) prior to starting and use for subsequent modifications of the value, since using the subscript operator is apparently not guaranteed to be thread safe for associative containers.



The subscript operator can modify the map if the key if the is not present, so it is not constitute and thus formally not thread safe even if you are sure the key is always present. At and find are always constitute so you can use those instead; no need to cache iterators.


> The subscript operator can modify the map if the key if the is not present, so it is not constitute and thus formally not thread safe even if you are sure the key is always present.

Yeah, I know why it is unsafe in general, but I don't see why the C++ standard can't specify that operations that don't invalidate iterators are legal to perform in a concurrent manner provided they touch disjoint memory locations (for associative containers, subscripting is defined to be one such operator, as long as rehashing does not occur like in this case).

> At and find are always constitute so you can use those instead; no need to cache iterators.

Now that you mention it, I could have just called find every time. I guess I'm too used to it being O(n) for other collections and avoided it somewhat irrationally ;)


The wording could be changed. I guess it is just an issue of the committee only having ago items time; as there are alternatives here getting the correct wording right is not a priority so the fallback to const/non-cons thread safety guarantees is sufficient.


If you didn't like caching the map iterator, you could have cached the pointer to the value object instead i.e. Foo* cached_value = &mymap[this_thread_id]. Although caching the map iterator sounds perfectly fine to me.


Isn't the whole point of iterators to prevent the above strategy from crashing your program when the map is moved to another region of memory?


I'm not exactly sure what you mean by "the map is moved to another region of memory", but a pointer to the value object in a map entry is safe (or unsafe) in exactly the same situations as an iterator into the map. Under the hood, the iterator is likely to be a pointer to a tree node struct that contains the key and value objects (along with pointers to other relevant nodes).




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: