private void process(Job job) { void count(string word) { if (!job.Cache.TryGetValue(word, out var counter)) // get from job cache (accessed within a single thread) { counter = _counters.putIfAbsent(word, // get from global map (create new one if not exists) new Counter { Word = word }); job.Cache.Add(word, counter); // store in job thread cache } Interlocked.Increment(ref counter.Value); } try { var lines = File.ReadLines(job.Path); // lazy evaluated line iterator foreach (var line in lines) { if (line.IsEmpty()) { continue; } var words = line.ToLower().Split(' '); // split to case insensitive words foreach (var word in words) { if (word == "") { continue; } count(word); } } } finally { job.Signal.Set(); } }
Value IConcurrentMap <Key, Value> .putIfAbsent(Key key, Value value) { lock (_mutex) return(_.putIfAbsent(key, value)); }