7

I am currently using Facebook's concurrent hash map and I am wondering if something like this would be possible:

folly::ConcurrentHashMap<std::string, some_class> m;

// add some elements

const auto it = m.find("a");

// during this time, another thread removes the "a" element

if (it != m.end())
    it->second.something(); // it is now an invalid iterator

After reading through the source of the hash map, I came across this:

Iterators hold hazard pointers to the returned elements. Elements can only be accessed while Iterators are still valid!

This is pretty unsettling and it feels like using any returned iterators are unsafe, is this so?

Community
  • 1
  • 1
Michael Smith
  • 1,271
  • 1
  • 8
  • 31
  • Any use? There are safe ways to use iterators. Obviously if you change or delete the elements they point to before using them then you're going to be on dodgy ground. – Galik Mar 22 '18 at 13:50
  • I think using anything in the folly namespace is ... well, folly ^_^ – UKMonkey Mar 22 '18 at 13:50
  • @Galik Well if you can't delete or change elements while reading them, what is the point of a concurrent hash map at all? – Michael Smith Mar 22 '18 at 13:51
  • 1
    @UKMonkey The folly is pretty clearly "well, std doesn't do what we want. Lets build ourself a replacement for std that does what we want. What could go wrong?" Either that, or https://en.wikipedia.org/wiki/Folly – Yakk - Adam Nevraumont Mar 22 '18 at 14:01
  • @Yakk or even https://en.oxforddictionaries.com/definition/folly – UKMonkey Mar 22 '18 at 14:13

1 Answers1

9

The returned iterators are safe to use; however, the iterator object must be alive for the dereferenced value to be safe to access.

The 'hazard pointer' keeps the referenced value alive until the iterator is destructed.

operator[] and at() return the actual value for the given key, and so can't return a proxy object containing the hazard pointer. To ensure that they never return a reference to a dead object they instead return a copy of the value.

Whether you use iterators, or operator[]/at(), you will be operating on the value for the key at the time that you accessed the data, rather than the latest value for the given key.

Mankarse
  • 39,818
  • 11
  • 97
  • 141