prometheus-net

Форк
0
/
NonCapturingLazyInitializer.cs 
140 строк · 4.3 Кб
1
// Licensed to the .NET Foundation under one or more agreements.
2
// The .NET Foundation licenses this file to you under the MIT license.
3

4
using System.Diagnostics;
5

6
namespace Prometheus;
7

8
// Copy-pasted from https://github.com/dotnet/efcore/blob/main/src/Shared/NonCapturingLazyInitializer.cs
9
// Crudely modified to inline dependencies and reduce functionality down to .NET Fx compatible level.
10
internal static class NonCapturingLazyInitializer
11
{
12
    public static TValue EnsureInitialized<TParam, TValue>(
13
        ref TValue? target,
14
        TParam param,
15
        Func<TParam, TValue> valueFactory)
16
        where TValue : class
17
    {
18
        var tmp = Volatile.Read(ref target);
19
        if (tmp != null)
20
        {
21
            DebugAssert(target != null, $"target was null in {nameof(EnsureInitialized)} after check");
22
            return tmp;
23
        }
24

25
        Interlocked.CompareExchange(ref target, valueFactory(param), null);
26

27
        return target;
28
    }
29

30
    public static TValue EnsureInitialized<TParam1, TParam2, TValue>(
31
        ref TValue? target,
32
        TParam1 param1,
33
        TParam2 param2,
34
        Func<TParam1, TParam2, TValue> valueFactory)
35
        where TValue : class
36
    {
37
        var tmp = Volatile.Read(ref target);
38
        if (tmp != null)
39
        {
40
            DebugAssert(target != null, $"target was null in {nameof(EnsureInitialized)} after check");
41
            return tmp;
42
        }
43

44
        Interlocked.CompareExchange(ref target, valueFactory(param1, param2), null);
45

46
        return target;
47
    }
48

49
    public static TValue EnsureInitialized<TParam1, TParam2, TParam3, TValue>(
50
        ref TValue? target,
51
        TParam1 param1,
52
        TParam2 param2,
53
        TParam3 param3,
54
        Func<TParam1, TParam2, TParam3, TValue> valueFactory)
55
        where TValue : class
56
    {
57
        var tmp = Volatile.Read(ref target);
58
        if (tmp != null)
59
        {
60
            DebugAssert(target != null, $"target was null in {nameof(EnsureInitialized)} after check");
61
            return tmp;
62
        }
63

64
        Interlocked.CompareExchange(ref target, valueFactory(param1, param2, param3), null);
65

66
        return target;
67
    }
68

69
    public static TValue EnsureInitialized<TParam, TValue>(
70
        ref TValue target,
71
        ref bool initialized,
72
        TParam param,
73
        Func<TParam, TValue> valueFactory)
74
        where TValue : class?
75
    {
76
        var alreadyInitialized = Volatile.Read(ref initialized);
77
        if (alreadyInitialized)
78
        {
79
            var value = Volatile.Read(ref target);
80
            DebugAssert(target != null, $"target was null in {nameof(EnsureInitialized)} after check");
81
            DebugAssert(value != null, $"value was null in {nameof(EnsureInitialized)} after check");
82
            return value;
83
        }
84

85
        Volatile.Write(ref target, valueFactory(param));
86
        Volatile.Write(ref initialized, true);
87

88
        return target;
89
    }
90

91
    public static TValue EnsureInitialized<TValue>(
92
        ref TValue? target,
93
        TValue value)
94
        where TValue : class
95
    {
96
        var tmp = Volatile.Read(ref target);
97
        if (tmp != null)
98
        {
99
            DebugAssert(target != null, $"target was null in {nameof(EnsureInitialized)} after check");
100
            return tmp;
101
        }
102

103
        Interlocked.CompareExchange(ref target, value, null);
104

105
        return target;
106
    }
107

108
    public static TValue EnsureInitialized<TParam, TValue>(
109
        ref TValue? target,
110
        TParam param,
111
        Action<TParam> valueFactory)
112
        where TValue : class
113
    {
114
        var tmp = Volatile.Read(ref target);
115
        if (tmp != null)
116
        {
117
            DebugAssert(target != null, $"target was null in {nameof(EnsureInitialized)} after check");
118
            return tmp;
119
        }
120

121
        valueFactory(param);
122

123
        var tmp2 = Volatile.Read(ref target);
124
        DebugAssert(
125
            target != null && tmp2 != null,
126
            $"{nameof(valueFactory)} did not initialize {nameof(target)} in {nameof(EnsureInitialized)}");
127
#pragma warning disable CS8603 // Possible null reference return.
128
        return tmp2;
129
#pragma warning restore CS8603 // Possible null reference return.
130
    }
131

132
    [Conditional("DEBUG")]
133
    private static void DebugAssert(bool condition, string message)
134
    {
135
        if (!condition)
136
        {
137
            throw new Exception($"Check.DebugAssert failed: {message}");
138
        }
139
    }
140
}
141

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.