You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
57 lines
2.1 KiB
57 lines
2.1 KiB
using System.Threading;
|
|
|
|
namespace Dapper
|
|
{
|
|
partial class SqlMapper
|
|
{
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
internal class Link<TKey, TValue> where TKey : class
|
|
{
|
|
public static bool TryGet(Link<TKey, TValue> 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<TKey, TValue> 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<TKey, TValue>(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<TKey, TValue> tail)
|
|
{
|
|
Key = key;
|
|
Value = value;
|
|
Tail = tail;
|
|
}
|
|
public TKey Key { get; }
|
|
public TValue Value { get; }
|
|
public Link<TKey, TValue> Tail { get; }
|
|
}
|
|
}
|
|
}
|
|
|