Исходный код вики Containers pool
Редактировал(а) Alexandr Fokin 2024/07/01 11:01
Последние авторы
author | version | line-number | content |
---|---|---|---|
1 | |(% style="width:65px" %) |(% style="width:1389px" %){{code language="c#"}}internal class PoolManager<T> | ||
2 | : IAsyncDisposable | ||
3 | { | ||
4 | private readonly Func<Task<T>> _createAction; | ||
5 | private readonly Func<Func<Task<T>>, T, ValueTask<T>> _resetAction; | ||
6 | private readonly Func<T, ValueTask> _disposeAction; | ||
7 | private readonly bool _canCreateNew; | ||
8 | private readonly Channel<T> _values; | ||
9 | |||
10 | #region | ||
11 | |||
12 | private PoolManager( | ||
13 | Func<Task<T>> createAction, | ||
14 | Func<Func<Task<T>>, T, ValueTask<T>> resetAction, | ||
15 | Func<T, ValueTask> disposeAction, | ||
16 | int? fixedSize, | ||
17 | IEnumerable<T>? values = null | ||
18 | ) | ||
19 | { | ||
20 | _createAction = createAction; | ||
21 | _resetAction = resetAction; | ||
22 | _disposeAction = disposeAction; | ||
23 | _canCreateNew = !fixedSize.HasValue; | ||
24 | |||
25 | if (fixedSize.HasValue) | ||
26 | { | ||
27 | _canCreateNew = false; | ||
28 | _values = Channel.CreateBounded<T>(fixedSize.Value); | ||
29 | } | ||
30 | else | ||
31 | { | ||
32 | _canCreateNew = true; | ||
33 | _values = Channel.CreateUnbounded<T>(); | ||
34 | } | ||
35 | |||
36 | if (values != null) | ||
37 | { | ||
38 | foreach (var elem in values) | ||
39 | { | ||
40 | if (!_values.Writer.TryWrite(elem)) | ||
41 | { | ||
42 | throw new Exception(); | ||
43 | } | ||
44 | } | ||
45 | } | ||
46 | } | ||
47 | |||
48 | |||
49 | public static PoolManager<T> Create( | ||
50 | Func<Task<T>> createAction, | ||
51 | Func<Func<Task<T>>, T, ValueTask<T>> resetAction, | ||
52 | Func<T, ValueTask> disposeAction | ||
53 | ) | ||
54 | { | ||
55 | return new PoolManager<T>( | ||
56 | createAction, | ||
57 | resetAction, | ||
58 | disposeAction, | ||
59 | fixedSize: null | ||
60 | ); | ||
61 | } | ||
62 | |||
63 | public static async Task<PoolManager<T>> CreateFixedAsync( | ||
64 | Func<Task<T>> createAction, | ||
65 | Func<Func<Task<T>>, T, ValueTask<T>> resetAction, | ||
66 | Func<T, ValueTask> disposeAction, | ||
67 | int initCount | ||
68 | ) | ||
69 | { | ||
70 | var createTasks = Enumerable.Repeat(true, initCount) | ||
71 | .Select(e => createAction()) | ||
72 | .ToArray(); | ||
73 | await Task.WhenAll(createTasks); | ||
74 | |||
75 | return new PoolManager<T>( | ||
76 | createAction, | ||
77 | resetAction, | ||
78 | disposeAction, | ||
79 | fixedSize: initCount, | ||
80 | values: createTasks.Select(e => e.Result) | ||
81 | ); | ||
82 | } | ||
83 | |||
84 | #endregion | ||
85 | |||
86 | |||
87 | #region | ||
88 | |||
89 | public async Task<PoolItem> GetAsync() | ||
90 | { | ||
91 | T value; | ||
92 | if (_canCreateNew) | ||
93 | { | ||
94 | if (!_values.Reader.TryRead(out value!)) | ||
95 | { | ||
96 | value = await _createAction(); | ||
97 | } | ||
98 | } | ||
99 | else | ||
100 | { | ||
101 | value = await _values.Reader.ReadAsync(); | ||
102 | } | ||
103 | |||
104 | return new PoolManager<T>.PoolItem( | ||
105 | this, | ||
106 | value | ||
107 | ); | ||
108 | } | ||
109 | |||
110 | public async ValueTask DisposeAsync() | ||
111 | { | ||
112 | List<Task> disposeTasks = new List<Task>(5); | ||
113 | while (_values.Reader.TryRead(out var elem)) | ||
114 | { | ||
115 | disposeTasks.Add( | ||
116 | _disposeAction(elem).AsTask() | ||
117 | ); | ||
118 | } | ||
119 | |||
120 | await Task.WhenAll(disposeTasks); | ||
121 | } | ||
122 | |||
123 | #endregion | ||
124 | |||
125 | |||
126 | #region | ||
127 | |||
128 | public record PoolItem | ||
129 | : IAsyncDisposable | ||
130 | { | ||
131 | private readonly PoolManager<T> _poolManager; | ||
132 | public T Value { get; } | ||
133 | |||
134 | |||
135 | public PoolItem( | ||
136 | PoolManager<T> poolManager, | ||
137 | T value | ||
138 | ) | ||
139 | { | ||
140 | _poolManager = poolManager; | ||
141 | Value = value; | ||
142 | } | ||
143 | |||
144 | public async ValueTask DisposeAsync() | ||
145 | { | ||
146 | var value = await _poolManager._resetAction(_poolManager._createAction, Value); | ||
147 | if (!_poolManager._values.Writer.TryWrite(value)) | ||
148 | { | ||
149 | throw new Exception(); | ||
150 | } | ||
151 | } | ||
152 | } | ||
153 | |||
154 | #endregion | ||
155 | }{{/code}} | ||
156 | |(% style="width:65px" %) |(% style="width:1389px" %)[[System. Threading. Channels>>doc:Разработка.NET.Библиотеки.События и потоки.System\. Threading\. Channels.WebHome]] | ||
157 | |(% style="width:65px" %) |(% style="width:1389px" %) | ||
158 | |||
159 |