using System.Threading; namespace Dapper { partial class SqlMapper { /// /// This is a micro-cache; suitable when the number of terms is controllable (a few hundred, for example), /// and strictly append-only; you cannot change existing values. All key matches are on **REFERENCE** /// equality. The type is fully thread-safe. /// internal class Link where TKey : class { public static bool TryGet(Link link, TKey key, out TValue value) { while (link != null) { if ((object)key == (object)link.Key) { value = link.Value; return true; } link = link.Tail; } value = default(TValue); return false; } public static bool TryAdd(ref Link head, TKey key, ref TValue value) { bool tryAgain; do { var snapshot = Interlocked.CompareExchange(ref head, null, null); TValue found; if (TryGet(snapshot, key, out found)) { // existing match; report the existing value instead value = found; return false; } var newNode = new Link(key, value, snapshot); // did somebody move our cheese? tryAgain = Interlocked.CompareExchange(ref head, newNode, snapshot) != snapshot; } while (tryAgain); return true; } private Link(TKey key, TValue value, Link tail) { Key = key; Value = value; Tail = tail; } public TKey Key { get; } public TValue Value { get; } public Link Tail { get; } } } }