using System; using System.Collections.Generic; using Microsoft.Ccr.Core; namespace Roblox { public interface IAsyncDictionary { void Add(TKey key, TValue value, Port result); void ContainsKey(TKey key, Port result); void Remove(TKey key, Port result); void TryGetValue(TKey key, PortSet result); void GetOrCreate(TKey key, Port result); } public class AsyncDictionary : IAsyncDictionary where TValue : new() { private readonly Interleaver interleaver = new Interleaver(); private readonly IDictionary dictionary = new Dictionary(); public void Add(TKey key, TValue value, Port result) { interleaver.DoExclusive(() => { dictionary.Add(key, value); result.Post(EmptyValue.SharedInstance); }); } public void GetOrCreate(TKey key, Port result) { interleaver.DoExclusive(() => { if (!dictionary.TryGetValue(key, out var value)) { value = new TValue(); dictionary.Add(key, value); } result.Post(value); }); } public void ContainsKey(TKey key, Port result) { interleaver.DoConcurrent(() => result.Post(dictionary.ContainsKey(key))); } public void Remove(TKey key, Port result) { interleaver.DoExclusive(() => result.Post(dictionary.Remove(key))); } public void TryGetValue(TKey key, PortSet result) { interleaver.DoConcurrent(() => { if (dictionary.TryGetValue(key, out var value)) { result.Post(value); return; } result.Post(EmptyValue.SharedInstance); }); } } public class ParallelDictionary : IAsyncDictionary where TValue : new() { private readonly AsyncDictionary[] dictionaries = new AsyncDictionary[64]; public ParallelDictionary() { for (int i = 0; i < dictionaries.Length; i++) dictionaries[i] = new AsyncDictionary(); } private AsyncDictionary GetDictionary(TKey key) { var hashCode = (uint)key.GetHashCode(); return dictionaries[(int)checked((IntPtr)(unchecked(hashCode % (ulong)dictionaries.Length)))]; } public void Add(TKey key, TValue value, Port result) { GetDictionary(key).Add(key, value, result); } public void ContainsKey(TKey key, Port result) { GetDictionary(key).ContainsKey(key, result); } public void Remove(TKey key, Port result) { GetDictionary(key).Remove(key, result); } public void TryGetValue(TKey key, PortSet result) { GetDictionary(key).TryGetValue(key, result); } public void GetOrCreate(TKey key, Port result) { GetDictionary(key).GetOrCreate(key, result); } } }