-
Notifications
You must be signed in to change notification settings - Fork 1
/
LocklessLazyWriteOnce.cs
67 lines (58 loc) · 2.04 KB
/
LocklessLazyWriteOnce.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
using System;
using System.Diagnostics;
using System.Threading;
using JetBrains.Annotations;
namespace HpTimeStamps
{
internal class LocklessLazyWriteOnce<T> where T : class
{
public bool IsSet => _value != null;
[NotNull]
public T Value
{
get
{
T ret = _value;
if (ret == null)
{
try
{
T temp = _initializer();
if (temp == null)
{
throw new DelegateReturnedNullException(nameof(_initializer), _initializer);
}
Interlocked.CompareExchange(ref _value, temp, null);
}
catch (DelegateException)
{
throw;
}
catch (Exception inner)
{
throw new DelegateThrewException(nameof(_initializer), _initializer, inner);
}
ret = _value;
}
Debug.Assert(ret != null);
return ret;
}
}
public bool TrySetNotDefaultValue([NotNull] T nonDefaultValue)
{
if (nonDefaultValue == null) throw new ArgumentNullException(nameof(nonDefaultValue));
return Interlocked.CompareExchange(ref _value, nonDefaultValue, null) == null;
}
public void SetNotDefaultValueOrThrow([NotNull] T nonDefaultValue)
{
if (!TrySetNotDefaultValue(nonDefaultValue))
{
throw new InvalidOperationException("The value has already been set.");
}
}
public LocklessLazyWriteOnce([NotNull] Func<T> initializer) =>
_initializer = initializer?? throw new ArgumentNullException(nameof(initializer));
private readonly Func<T> _initializer;
[CanBeNull] private volatile T _value;
}
}