public void HopscotchMap() { var map = new HopscotchMap <int, int>(8, 10000); var bag = new ConcurrentBag <int>(); var completitionSources = new TaskCompletionSource <bool> [8]; int initialID = new Random().Next(1000000); for (int i = 0; i < completitionSources.Length; i++) { int j = i; completitionSources[j] = new TaskCompletionSource <bool>(); new Thread(() => { ComplexTest(map, MapCapacity, bag, j + initialID); completitionSources[j].SetResult(true); }).Start(); } Task[] tasks = completitionSources.Select(t => t.Task).ToArray(); Task.WaitAll(tasks); var errors = tasks.Where(t => t.IsFaulted).Select(t => t.Exception).ToArray(); if (errors.Length > 0) { throw new AggregateException(errors); } }
private HopscotchMap(HopscotchMap <TKey, TValue> original) { keyComparer = original.keyComparer; segmentShift = original.segmentShift; segmentMask = original.segmentMask; bucketMask = original.bucketMask; segments = new Segment[original.segments.Length]; for (int i = 0; i < segments.Length; i++) { segments[i] = new Segment(); segments[i].timestamp = original.segments[i].timestamp; } table = (Bucket[])original.table.Clone(); }
static void ComplexTest(HopscotchMap <int, int> map, int capacity, ConcurrentBag <int> bag, int id) { var random = new Random(id); var clone = map; for (int i = 0; i < capacity * 1000; i++) { if (random.Next(100) < 40 || bag.Count > capacity * 2 / 3) { int element; if (bag.TryTake(out element)) { int data; if (!map.Remove(element, out data)) { throw new InvalidOperationException("Cannot remove element"); } if (data != element) { throw new InvalidOperationException("Data doesn't match key"); } } } else { int key = random.Next(capacity * 3); var result = map.PutIfAbsent(key, key); if (result == PutResult.Success) { if (!map.ContainsKey(key)) { throw new InvalidOperationException("no key after insert"); } bag.Add(key); } } } }