views:

155

answers:

1

Suppose you had this:

def wipeProduct(hash, nameToDelete) 
  hash.each do |i| 
    key = i[0]
    productName = i[1].first
    hash.delete(key) if productName==nameToDelete
  end
end

I'm not sure it's safe to delete things from a hash whilst you're iterating over the key-value pairs of the hash. I checked the RI documentation but I haven't seen anything about concurrent modification on Hash.

I know that you can rewrite this

def wipeProduct(hash, nameToDelete) 
  keysToDelete = []
  hash.each do |i| 
    key = i[0]
    productName = i[1].first
    keysToDelete << key if productName==nameToDelete
  end
  keysToDelete.each {|key| hash.delete(key) }
end

or even:

def wipeProduct(hash, nameToDelete)
  hash.reject!{|key,value| nameToDelete==value.first}
end

but I want to know if concurrent modification as shown in the first example above is a problem? (It doesn't seem to be when I run the code)

Question: Does anyone know what the position on concurrent modification is with Hash? (... and the other collections?) - and I'd certainly like any links to resources documenting this if you would please.

+1  A: 

As long as no other threads are trying to access the hash, any of those method are fine. If there are any other threads that could access this hash, then none of these approaches are explicitly thread safe. You'll want to make them tread safe, just ensure that your method acquires a lock during the hash modification, and things would work out fine.

Personally I'd go with the destructive reject_if! It's cleaner code and accomplishes the same thing without reproducing existing code.

EmFi