let info = new SortedDictionary<string, string> ... Thread A -------- info.Add("abc", "def") Thread B -------- info |> Seq.iteri (fun i value -> ...
Where do I place the readLock when I use the iteri function?
let info = new SortedDictionary<string, string> ... Thread A -------- info.Add("abc", "def") Thread B -------- info |> Seq.iteri (fun i value -> ...
Where do I place the readLock when I use the iteri function?
You may want to just side-step the problem of mutability, and use an immutable Map instead of SortedDictionary. This way, your iteration works on a "snapshot" of the data structure, with no worries about it getting changed out from underneath you. Then, you only need to lock your initial grab of the snapshot.
For example (warning, have not tested to see if this is actually threadsafe!):
let mymap = ref Map<string,string>.Empty
let safefetch m = lock(m) (fun () -> !m)
let safeadd k v m = lock(m) (fun () -> m := Map.add k v !m)
mymap
|> safefetch
|> Map.iter ( fun k v -> printfn "%s: %s" k v )
mymap |> safeadd "test" "value"
After some thinking it seems that placing a lock on Seq.iteri does actually make no sense since a Seq is lazy in F#.
However it is interesting to note that an exception is thrown when additional elements of a dictionary are inserted by another thread during the iteration of the sequence. Not sure if that is fully warranted for a lazy iteration.
My solution (as a function) right now is:
(fun _ -> lock info (fun _ -> info |> Seq.iteri (fun i x -> ...)))
I hope it is OK to answer my own question (I am new here).